Merge "Clean up system service registration. (2nd try)"
diff --git a/Android.bp b/Android.bp
index 5070b5e..e7a3efc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -916,28 +916,6 @@
     ],
 }
 
-// TODO: Don't rely on this list by switching package.html into package-info.java
-frameworks_base_subdirs = [
-    "core/java",
-    "graphics/java",
-    "location/java",
-    "media/java",
-    "media/mca/effect/java",
-    "media/mca/filterfw/java",
-    "media/mca/filterpacks/java",
-    "drm/java",
-    "mms/java",
-    "opengl/java",
-    "sax/java",
-    "telecomm/java",
-    "telephony/common",
-    "telephony/java",
-    "wifi/java",
-    "lowpan/java",
-    "keystore/java",
-    "rs/java",
-]
-
 // Make the api/current.txt file available for use by modules in other
 // directories.
 filegroup {
@@ -1042,7 +1020,6 @@
         "test-runner/src/**/*.java",
     ],
     libs: framework_docs_only_libs,
-    local_sourcepaths: frameworks_base_subdirs,
     create_doc_stubs: true,
     annotations_enabled: true,
     api_levels_annotations_enabled: true,
@@ -1103,7 +1080,6 @@
         ":updatable-media-srcs",
     ],
     libs: ["framework-internal-utils"],
-    local_sourcepaths: frameworks_base_subdirs,
     installable: false,
     annotations_enabled: true,
     previous_api: ":last-released-public-api-for-metalava-annotations",
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 4ee46f4..dfe7a90 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -1390,8 +1390,10 @@
     private static final int MSG_FINISH_IDLE_OP = 8;
     private static final int MSG_REPORT_TEMP_APP_WHITELIST_CHANGED = 9;
     private static final int MSG_SEND_CONSTRAINT_MONITORING = 10;
-    private static final int MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR = 11;
-    private static final int MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR = 12;
+    @VisibleForTesting
+    static final int MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR = 11;
+    @VisibleForTesting
+    static final int MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR = 12;
 
     final class MyHandler extends Handler {
         MyHandler(Looper looper) {
@@ -3327,8 +3329,7 @@
         mHandler.sendEmptyMessage(MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR);
     }
 
-    @VisibleForTesting
-    void updatePreIdleFactor() {
+    private void updatePreIdleFactor() {
         synchronized (this) {
             if (!shouldUseIdleTimeoutFactorLocked()) {
                 return;
@@ -3350,8 +3351,7 @@
         }
     }
 
-    @VisibleForTesting
-    void maybeDoImmediateMaintenance() {
+    private void maybeDoImmediateMaintenance() {
         synchronized (this) {
             if (mState == STATE_IDLE) {
                 long duration = SystemClock.elapsedRealtime() - mIdleStartTime;
@@ -3377,6 +3377,7 @@
     void setIdleStartTimeForTest(long idleStartTime) {
         synchronized (this) {
             mIdleStartTime = idleStartTime;
+            maybeDoImmediateMaintenance();
         }
     }
 
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 a0615aa..8a00c83 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -1179,7 +1179,7 @@
         long token = Binder.clearCallingIdentity();
         synchronized (this) {
             if (mTelephony == null) {
-                mTelephony = TelephonyManager.from(mContext);
+                mTelephony = mContext.getSystemService(TelephonyManager.class);
             }
         }
         if (mTelephony != null) {
diff --git a/api/current.txt b/api/current.txt
index 7c3ce1e..61013e8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8445,6 +8445,7 @@
     method public int describeContents();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean fetchUuidsWithSdp();
     method public String getAddress();
+    method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public String getAlias();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothClass getBluetoothClass();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getBondState();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public String getName();
@@ -8456,6 +8457,7 @@
     field public static final String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED";
     field public static final String ACTION_ACL_DISCONNECTED = "android.bluetooth.device.action.ACL_DISCONNECTED";
     field public static final String ACTION_ACL_DISCONNECT_REQUESTED = "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";
+    field public static final String ACTION_ALIAS_CHANGED = "android.bluetooth.action.ALIAS_CHANGED";
     field public static final String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED";
     field public static final String ACTION_CLASS_CHANGED = "android.bluetooth.device.action.CLASS_CHANGED";
     field public static final String ACTION_FOUND = "android.bluetooth.device.action.FOUND";
@@ -9475,6 +9477,7 @@
     method @Nullable public android.net.Uri canonicalize(@NonNull android.net.Uri);
     method @NonNull public final android.content.ContentProvider.CallingIdentity clearCallingIdentity();
     method public abstract int delete(@NonNull android.net.Uri, @Nullable String, @Nullable String[]);
+    method public int delete(@NonNull android.net.Uri, @Nullable android.os.Bundle);
     method public void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
     method @Nullable public final String getCallingFeatureId();
     method @Nullable public final String getCallingPackage();
@@ -9485,6 +9488,7 @@
     method @Nullable public abstract String getType(@NonNull android.net.Uri);
     method @Nullable public final String getWritePermission();
     method @Nullable public abstract android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues);
+    method @Nullable public android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
     method protected boolean isTemporary();
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public abstract boolean onCreate();
@@ -9510,6 +9514,7 @@
     method public void shutdown();
     method @Nullable public android.net.Uri uncanonicalize(@NonNull android.net.Uri);
     method public abstract int update(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]);
+    method public int update(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
   }
 
   public final class ContentProvider.CallingIdentity {
@@ -9528,10 +9533,12 @@
     method @Nullable public final android.net.Uri canonicalize(@NonNull android.net.Uri) throws android.os.RemoteException;
     method public void close();
     method public int delete(@NonNull android.net.Uri, @Nullable String, @Nullable String[]) throws android.os.RemoteException;
+    method public int delete(@NonNull android.net.Uri, @Nullable android.os.Bundle) throws android.os.RemoteException;
     method @Nullable public android.content.ContentProvider getLocalContentProvider();
     method @Nullable public String[] getStreamTypes(@NonNull android.net.Uri, @NonNull String) throws android.os.RemoteException;
     method @Nullable public String getType(@NonNull android.net.Uri) throws android.os.RemoteException;
     method @Nullable public android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues) throws android.os.RemoteException;
+    method @Nullable public android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle) throws android.os.RemoteException;
     method @Nullable public android.content.res.AssetFileDescriptor openAssetFile(@NonNull android.net.Uri, @NonNull String) throws java.io.FileNotFoundException, android.os.RemoteException;
     method @Nullable public android.content.res.AssetFileDescriptor openAssetFile(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
     method @Nullable public android.os.ParcelFileDescriptor openFile(@NonNull android.net.Uri, @NonNull String) throws java.io.FileNotFoundException, android.os.RemoteException;
@@ -9546,6 +9553,7 @@
     method @Deprecated public boolean release();
     method @Nullable public final android.net.Uri uncanonicalize(@NonNull android.net.Uri) throws android.os.RemoteException;
     method public int update(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]) throws android.os.RemoteException;
+    method public int update(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle) throws android.os.RemoteException;
   }
 
   public class ContentProviderOperation implements android.os.Parcelable {
@@ -9633,6 +9641,7 @@
     method public static void cancelSync(android.content.SyncRequest);
     method @Nullable public final android.net.Uri canonicalize(@NonNull android.net.Uri);
     method public final int delete(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable String, @Nullable String[]);
+    method public final int delete(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.os.Bundle);
     method @Deprecated public static android.content.SyncInfo getCurrentSync();
     method public static java.util.List<android.content.SyncInfo> getCurrentSyncs();
     method public static int getIsSyncable(android.accounts.Account, String);
@@ -9646,6 +9655,7 @@
     method @Nullable public final String getType(@NonNull android.net.Uri);
     method @NonNull public final android.content.ContentResolver.MimeTypeInfo getTypeInfo(@NonNull String);
     method @Nullable public final android.net.Uri insert(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues);
+    method @Nullable public final android.net.Uri insert(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
     method public static boolean isSyncActive(android.accounts.Account, String);
     method public static boolean isSyncPending(android.accounts.Account, String);
     method @NonNull public android.graphics.Bitmap loadThumbnail(@NonNull android.net.Uri, @NonNull android.util.Size, @Nullable android.os.CancellationSignal) throws java.io.IOException;
@@ -9683,6 +9693,7 @@
     method @Nullable public final android.net.Uri uncanonicalize(@NonNull android.net.Uri);
     method public final void unregisterContentObserver(@NonNull android.database.ContentObserver);
     method public final int update(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]);
+    method public final int update(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
     method public static void validateSyncExtrasBundle(android.os.Bundle);
     method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProvider);
     method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProviderClient);
@@ -9695,12 +9706,16 @@
     field public static final String EXTRA_TOTAL_COUNT = "android.content.extra.TOTAL_COUNT";
     field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
     field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
+    field public static final String QUERY_ARG_GROUP_COLUMNS = "android:query-arg-group-columns";
     field public static final String QUERY_ARG_LIMIT = "android:query-arg-limit";
     field public static final String QUERY_ARG_OFFSET = "android:query-arg-offset";
     field public static final String QUERY_ARG_SORT_COLLATION = "android:query-arg-sort-collation";
     field public static final String QUERY_ARG_SORT_COLUMNS = "android:query-arg-sort-columns";
     field public static final String QUERY_ARG_SORT_DIRECTION = "android:query-arg-sort-direction";
     field public static final String QUERY_ARG_SORT_LOCALE = "android:query-arg-sort-locale";
+    field public static final String QUERY_ARG_SQL_GROUP_BY = "android:query-arg-sql-group-by";
+    field public static final String QUERY_ARG_SQL_HAVING = "android:query-arg-sql-having";
+    field public static final String QUERY_ARG_SQL_LIMIT = "android:query-arg-sql-limit";
     field public static final String QUERY_ARG_SQL_SELECTION = "android:query-arg-sql-selection";
     field public static final String QUERY_ARG_SQL_SELECTION_ARGS = "android:query-arg-sql-selection-args";
     field public static final String QUERY_ARG_SQL_SORT_ORDER = "android:query-arg-sql-sort-order";
@@ -39009,10 +39024,14 @@
     field public static final String ACTION_VPN_SETTINGS = "android.settings.VPN_SETTINGS";
     field public static final String ACTION_VR_LISTENER_SETTINGS = "android.settings.VR_LISTENER_SETTINGS";
     field public static final String ACTION_WEBVIEW_SETTINGS = "android.settings.WEBVIEW_SETTINGS";
+    field public static final String ACTION_WIFI_ADD_NETWORKS = "android.settings.WIFI_ADD_NETWORKS";
     field public static final String ACTION_WIFI_IP_SETTINGS = "android.settings.WIFI_IP_SETTINGS";
     field public static final String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS";
     field public static final String ACTION_WIRELESS_SETTINGS = "android.settings.WIRELESS_SETTINGS";
     field public static final String ACTION_ZEN_MODE_PRIORITY_SETTINGS = "android.settings.ZEN_MODE_PRIORITY_SETTINGS";
+    field public static final int ADD_WIFI_RESULT_ADD_OR_UPDATE_FAILED = 1; // 0x1
+    field public static final int ADD_WIFI_RESULT_ALREADY_EXISTS = 2; // 0x2
+    field public static final int ADD_WIFI_RESULT_SUCCESS = 0; // 0x0
     field public static final String AUTHORITY = "settings";
     field public static final String EXTRA_ACCOUNT_TYPES = "account_types";
     field public static final String EXTRA_AIRPLANE_MODE_ENABLED = "airplane_mode_enabled";
@@ -39025,6 +39044,8 @@
     field public static final String EXTRA_INPUT_METHOD_ID = "input_method_id";
     field public static final String EXTRA_NOTIFICATION_LISTENER_COMPONENT_NAME = "android.provider.extra.NOTIFICATION_LISTENER_COMPONENT_NAME";
     field public static final String EXTRA_SUB_ID = "android.provider.extra.SUB_ID";
+    field public static final String EXTRA_WIFI_CONFIGURATION_LIST = "android.provider.extra.WIFI_CONFIGURATION_LIST";
+    field public static final String EXTRA_WIFI_CONFIGURATION_RESULT_LIST = "android.provider.extra.WIFI_CONFIGURATION_RESULT_LIST";
     field public static final String INTENT_CATEGORY_USAGE_ACCESS_CONFIG = "android.intent.category.USAGE_ACCESS_CONFIG";
     field public static final String METADATA_USAGE_ACCESS_REASON = "android.settings.metadata.USAGE_ACCESS_REASON";
   }
@@ -45245,6 +45266,7 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.os.ParcelUuid createSubscriptionGroup(@NonNull java.util.List<java.lang.Integer>);
     method @Deprecated public static android.telephony.SubscriptionManager from(android.content.Context);
     method public java.util.List<android.telephony.SubscriptionInfo> getAccessibleSubscriptionInfoList();
+    method @Nullable public java.util.List<android.telephony.SubscriptionInfo> getActiveAndHiddenSubscriptionInfoList();
     method public static int getActiveDataSubscriptionId();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfo(int);
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getActiveSubscriptionInfoCount();
diff --git a/api/system-current.txt b/api/system-current.txt
index 41b7a91..d91ecd4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1306,6 +1306,7 @@
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isEncrypted();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInSilenceMode();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean removeBond();
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean setAlias(@NonNull String);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setMetadata(int, @NonNull byte[]);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setPhonebookAccessPermission(int);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setSilenceMode(boolean);
@@ -2000,6 +2001,7 @@
     method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
     method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
     method public android.util.Pair<float[],float[]> getCurve();
+    method public boolean shouldCollectColorSamples();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
   }
@@ -2012,6 +2014,7 @@
     method public int getMaxCorrectionsByCategory();
     method public int getMaxCorrectionsByPackageName();
     method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
+    method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
   }
 
   public final class BrightnessCorrection implements android.os.Parcelable {
@@ -8485,6 +8488,7 @@
   public class SubscriptionInfo implements android.os.Parcelable {
     method @Nullable public java.util.List<android.telephony.UiccAccessRule> getAccessRules();
     method public int getProfileClass();
+    method public boolean isGroupDisabled();
   }
 
   public class SubscriptionManager {
@@ -8567,6 +8571,7 @@
     method @Deprecated public boolean getDataEnabled();
     method @Deprecated public boolean getDataEnabled(int);
     method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean);
+    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 @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
@@ -8598,7 +8603,9 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
+    method public boolean isModemEnabledForSlot(int);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
@@ -8619,6 +8626,7 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean);
diff --git a/api/test-current.txt b/api/test-current.txt
index 44f736c..c6b02b9 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1018,6 +1018,7 @@
     method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
     method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
     method public android.util.Pair<float[],float[]> getCurve();
+    method public boolean shouldCollectColorSamples();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
   }
@@ -1030,6 +1031,7 @@
     method public int getMaxCorrectionsByCategory();
     method public int getMaxCorrectionsByPackageName();
     method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
+    method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
   }
 
   public final class BrightnessCorrection implements android.os.Parcelable {
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 7e278e9..59544a9 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -508,7 +508,7 @@
 
         @Override
         public void onExecute(IContentProvider provider) throws Exception {
-            provider.insert(resolveCallingPackage(), null, mUri, mContentValues);
+            provider.insert(resolveCallingPackage(), null, mUri, mContentValues, null);
         }
     }
 
@@ -522,7 +522,8 @@
 
         @Override
         public void onExecute(IContentProvider provider) throws Exception {
-            provider.delete(resolveCallingPackage(), null, mUri, mWhere, null);
+            provider.delete(resolveCallingPackage(), null, mUri,
+                    ContentResolver.createSqlQueryBundle(mWhere, null));
         }
     }
 
@@ -679,7 +680,8 @@
 
         @Override
         public void onExecute(IContentProvider provider) throws Exception {
-            provider.update(resolveCallingPackage(), null, mUri, mContentValues, mWhere, null);
+            provider.update(resolveCallingPackage(), null, mUri, mContentValues,
+                    ContentResolver.createSqlQueryBundle(mWhere, null));
         }
     }
 
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 6d63fd09..590b3db 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -70,6 +70,7 @@
 import android.util.DisplayMetrics;
 import android.util.Singleton;
 import android.util.Size;
+import android.view.IWindowContainer;
 
 import com.android.internal.app.LocalePicker;
 import com.android.internal.app.procstats.ProcessStats;
@@ -2526,6 +2527,7 @@
         // Index of the stack in the display's stack list, can be used for comparison of stack order
         @UnsupportedAppUsage
         public int position;
+        public IWindowContainer stackToken;
         /**
          * The full configuration the stack is currently running in.
          * @hide
@@ -2559,6 +2561,7 @@
             dest.writeInt(userId);
             dest.writeInt(visible ? 1 : 0);
             dest.writeInt(position);
+            dest.writeStrongInterface(stackToken);
             if (topActivity != null) {
                 dest.writeInt(1);
                 topActivity.writeToParcel(dest, 0);
@@ -2590,6 +2593,7 @@
             userId = source.readInt();
             visible = source.readInt() > 0;
             position = source.readInt();
+            stackToken = IWindowContainer.Stub.asInterface(source.readStrongBinder());
             if (source.readInt() > 0) {
                 topActivity = ComponentName.readFromParcel(source);
             }
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index c616044..19f42b6 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -173,13 +173,10 @@
      * changed.
      * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
-     *
-     * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    @UnsupportedAppUsage
     public static final String ACTION_ALIAS_CHANGED =
-            "android.bluetooth.device.action.ALIAS_CHANGED";
+            "android.bluetooth.action.ALIAS_CHANGED";
 
     /**
      * Broadcast Action: Indicates a change in the bond state of a remote
@@ -1048,10 +1045,11 @@
      * Get the Bluetooth alias of the remote device.
      * <p>Alias is the locally modified name of a remote device.
      *
-     * @return the Bluetooth alias, or null if no alias or there was a problem
-     * @hide
+     * @return the Bluetooth alias, the friendly device name if no alias, or
+     * null if there was a problem
      */
-    @UnsupportedAppUsage(publicAlternatives = "Use {@link #getName()} instead.")
+    @Nullable
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public String getAlias() {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1059,7 +1057,11 @@
             return null;
         }
         try {
-            return service.getRemoteAlias(this);
+            String alias = service.getRemoteAlias(this);
+            if (alias == null) {
+                return getName();
+            }
+            return alias;
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1076,8 +1078,9 @@
      * @return true on success, false on error
      * @hide
      */
-    @UnsupportedAppUsage
-    public boolean setAlias(String alias) {
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public boolean setAlias(@NonNull String alias) {
         final IBluetooth service = sService;
         if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
diff --git a/core/java/android/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java
index 75e726b..0f67f6b 100644
--- a/core/java/android/companion/BluetoothDeviceFilterUtils.java
+++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java
@@ -129,7 +129,7 @@
 
     @UnsupportedAppUsage
     public static String getDeviceDisplayNameInternal(@NonNull BluetoothDevice device) {
-        return firstNotEmpty(device.getAliasName(), device.getAddress());
+        return firstNotEmpty(device.getAlias(), device.getAddress());
     }
 
     @UnsupportedAppUsage
diff --git a/core/java/android/content/ContentInterface.java b/core/java/android/content/ContentInterface.java
index 197de97..5988dd3 100644
--- a/core/java/android/content/ContentInterface.java
+++ b/core/java/android/content/ContentInterface.java
@@ -53,23 +53,22 @@
 
     public @Nullable Uri uncanonicalize(@NonNull Uri uri) throws RemoteException;
 
-    public boolean refresh(@NonNull Uri uri, @Nullable Bundle args,
+    public boolean refresh(@NonNull Uri uri, @Nullable Bundle extras,
             @Nullable CancellationSignal cancellationSignal) throws RemoteException;
 
     public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags)
             throws RemoteException;
 
-    public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues)
-            throws RemoteException;
+    public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues,
+            @Nullable Bundle extras) throws RemoteException;
 
     public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] initialValues)
             throws RemoteException;
 
-    public int delete(@NonNull Uri uri, @Nullable String selection,
-            @Nullable String[] selectionArgs) throws RemoteException;
+    public int delete(@NonNull Uri uri, @Nullable Bundle extras) throws RemoteException;
 
-    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
-            @Nullable String[] selectionArgs) throws RemoteException;
+    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable Bundle extras)
+            throws RemoteException;
 
     public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
             @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException;
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 17f1a07..2240823 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -299,7 +299,7 @@
 
         @Override
         public Uri insert(String callingPkg, @Nullable String featureId, Uri uri,
-                ContentValues initialValues) {
+                ContentValues initialValues, Bundle extras) {
             uri = validateIncomingUri(uri);
             int userId = getUserIdFromUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
@@ -317,7 +317,7 @@
             final Pair<String, String> original = setCallingPackage(
                     new Pair<>(callingPkg, featureId));
             try {
-                return maybeAddUserId(mInterface.insert(uri, initialValues), userId);
+                return maybeAddUserId(mInterface.insert(uri, initialValues, extras), userId);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
@@ -403,8 +403,7 @@
         }
 
         @Override
-        public int delete(String callingPkg, @Nullable String featureId, Uri uri, String selection,
-                String[] selectionArgs) {
+        public int delete(String callingPkg, @Nullable String featureId, Uri uri, Bundle extras) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             if (enforceWritePermission(callingPkg, featureId, uri, null)
@@ -415,7 +414,7 @@
             final Pair<String, String> original = setCallingPackage(
                     new Pair<>(callingPkg, featureId));
             try {
-                return mInterface.delete(uri, selection, selectionArgs);
+                return mInterface.delete(uri, extras);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
@@ -426,7 +425,7 @@
 
         @Override
         public int update(String callingPkg, @Nullable String featureId, Uri uri,
-                ContentValues values, String selection, String[] selectionArgs) {
+                ContentValues values, Bundle extras) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             if (enforceWritePermission(callingPkg, featureId, uri, null)
@@ -437,7 +436,7 @@
             final Pair<String, String> original = setCallingPackage(
                     new Pair<>(callingPkg, featureId));
             try {
-                return mInterface.update(uri, values, selection, selectionArgs);
+                return mInterface.update(uri, values, extras);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
@@ -593,7 +592,7 @@
         }
 
         @Override
-        public boolean refresh(String callingPkg, String featureId, Uri uri, Bundle args,
+        public boolean refresh(String callingPkg, String featureId, Uri uri, Bundle extras,
                 ICancellationSignal cancellationSignal) throws RemoteException {
             uri = validateIncomingUri(uri);
             uri = getUriWithoutUserId(uri);
@@ -605,7 +604,7 @@
             final Pair<String, String> original = setCallingPackage(
                     new Pair<>(callingPkg, featureId));
             try {
-                return mInterface.refresh(uri, args,
+                return mInterface.refresh(uri, extras,
                         CancellationSignal.fromTransport(cancellationSignal));
             } finally {
                 setCallingPackage(original);
@@ -1494,29 +1493,34 @@
     }
 
     /**
-     * Implement this to support refresh of content identified by {@code uri}. By default, this
-     * method returns false; providers who wish to implement this should return true to signal the
-     * client that the provider has tried refreshing with its own implementation.
+     * Implement this to support refresh of content identified by {@code uri}.
+     * By default, this method returns false; providers who wish to implement
+     * this should return true to signal the client that the provider has tried
+     * refreshing with its own implementation.
      * <p>
-     * This allows clients to request an explicit refresh of content identified by {@code uri}.
+     * This allows clients to request an explicit refresh of content identified
+     * by {@code uri}.
      * <p>
-     * Client code should only invoke this method when there is a strong indication (such as a user
-     * initiated pull to refresh gesture) that the content is stale.
+     * Client code should only invoke this method when there is a strong
+     * indication (such as a user initiated pull to refresh gesture) that the
+     * content is stale.
      * <p>
-     * Remember to send {@link ContentResolver#notifyChange(Uri, android.database.ContentObserver)}
+     * Remember to send
+     * {@link ContentResolver#notifyChange(Uri, android.database.ContentObserver)}
      * notifications when content changes.
      *
      * @param uri The Uri identifying the data to refresh.
-     * @param args Additional options from the client. The definitions of these are specific to the
-     *            content provider being called.
-     * @param cancellationSignal A signal to cancel the operation in progress, or {@code null} if
-     *            none. For example, if you called refresh on a particular uri, you should call
-     *            {@link CancellationSignal#throwIfCanceled()} to check whether the client has
-     *            canceled the refresh request.
+     * @param extras Additional options from the client. The definitions of
+     *            these are specific to the content provider being called.
+     * @param cancellationSignal A signal to cancel the operation in progress,
+     *            or {@code null} if none. For example, if you called refresh on
+     *            a particular uri, you should call
+     *            {@link CancellationSignal#throwIfCanceled()} to check whether
+     *            the client has canceled the refresh request.
      * @return true if the provider actually tried refreshing.
      */
     @Override
-    public boolean refresh(Uri uri, @Nullable Bundle args,
+    public boolean refresh(Uri uri, @Nullable Bundle extras,
             @Nullable CancellationSignal cancellationSignal) {
         return false;
     }
@@ -1545,20 +1549,42 @@
     }
 
     /**
-     * Implement this to handle requests to insert a new row.
-     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
-     * after inserting.
-     * This method can be called from multiple threads, as described in
-     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+     * Implement this to handle requests to insert a new row. As a courtesy,
+     * call
+     * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+     * notifyChange()} after inserting. This method can be called from multiple
+     * threads, as described in <a href="
+     * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
      * and Threads</a>.
+     *
      * @param uri The content:// URI of the insertion request.
      * @param values A set of column_name/value pairs to add to the database.
      * @return The URI for the newly inserted item.
      */
-    @Override
     public abstract @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values);
 
     /**
+     * Implement this to handle requests to insert a new row. As a courtesy,
+     * call
+     * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+     * notifyChange()} after inserting. This method can be called from multiple
+     * threads, as described in <a href="
+     * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+     * and Threads</a>.
+     *
+     * @param uri The content:// URI of the insertion request.
+     * @param values A set of column_name/value pairs to add to the database.
+     * @param extras A Bundle containing all additional information necessary
+     *            for the insert.
+     * @return The URI for the newly inserted item.
+     */
+    @Override
+    public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values,
+            @Nullable Bundle extras) {
+        return insert(uri, values);
+    }
+
+    /**
      * Override this to handle requests to insert a set of new rows, or the
      * default implementation will iterate over the values and call
      * {@link #insert} on each of them.
@@ -1583,50 +1609,111 @@
     }
 
     /**
-     * Implement this to handle requests to delete one or more rows.
-     * The implementation should apply the selection clause when performing
+     * Implement this to handle requests to delete one or more rows. The
+     * implementation should apply the selection clause when performing
      * deletion, allowing the operation to affect multiple rows in a directory.
-     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
-     * after deleting.
-     * This method can be called from multiple threads, as described in
-     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+     * As a courtesy, call
+     * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+     * notifyChange()} after deleting. This method can be called from multiple
+     * threads, as described in <a href="
+     * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
      * and Threads</a>.
+     * <p>
+     * The implementation is responsible for parsing out a row ID at the end of
+     * the URI, if a specific row is being deleted. That is, the client would
+     * pass in <code>content://contacts/people/22</code> and the implementation
+     * is responsible for parsing the record number (22) when creating a SQL
+     * statement.
      *
-     * <p>The implementation is responsible for parsing out a row ID at the end
-     * of the URI, if a specific row is being deleted. That is, the client would
-     * pass in <code>content://contacts/people/22</code> and the implementation is
-     * responsible for parsing the record number (22) when creating a SQL statement.
-     *
-     * @param uri The full URI to query, including a row ID (if a specific record is requested).
+     * @param uri The full URI to query, including a row ID (if a specific
+     *            record is requested).
      * @param selection An optional restriction to apply to rows when deleting.
      * @return The number of rows affected.
      * @throws SQLException
      */
-    @Override
     public abstract int delete(@NonNull Uri uri, @Nullable String selection,
             @Nullable String[] selectionArgs);
 
     /**
-     * Implement this to handle requests to update one or more rows.
-     * The implementation should update all rows matching the selection
-     * to set the columns according to the provided values map.
-     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
-     * after updating.
-     * This method can be called from multiple threads, as described in
-     * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+     * Implement this to handle requests to delete one or more rows. The
+     * implementation should apply the selection clause when performing
+     * deletion, allowing the operation to affect multiple rows in a directory.
+     * As a courtesy, call
+     * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+     * notifyChange()} after deleting. This method can be called from multiple
+     * threads, as described in <a href="
+     * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+     * and Threads</a>.
+     * <p>
+     * The implementation is responsible for parsing out a row ID at the end of
+     * the URI, if a specific row is being deleted. That is, the client would
+     * pass in <code>content://contacts/people/22</code> and the implementation
+     * is responsible for parsing the record number (22) when creating a SQL
+     * statement.
+     *
+     * @param uri The full URI to query, including a row ID (if a specific
+     *            record is requested).
+     * @param extras A Bundle containing all additional information necessary
+     *            for the delete. Values in the Bundle may include SQL style
+     *            arguments.
+     * @return The number of rows affected.
+     * @throws SQLException
+     */
+    @Override
+    public int delete(@NonNull Uri uri, @Nullable Bundle extras) {
+        extras = (extras != null) ? extras : Bundle.EMPTY;
+        return delete(uri,
+                extras.getString(ContentResolver.QUERY_ARG_SQL_SELECTION),
+                extras.getStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS));
+    }
+
+    /**
+     * Implement this to handle requests to update one or more rows. The
+     * implementation should update all rows matching the selection to set the
+     * columns according to the provided values map. As a courtesy, call
+     * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+     * notifyChange()} after updating. This method can be called from multiple
+     * threads, as described in <a href="
+     * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
      * and Threads</a>.
      *
-     * @param uri The URI to query. This can potentially have a record ID if this
-     * is an update request for a specific record.
+     * @param uri The URI to query. This can potentially have a record ID if
+     *            this is an update request for a specific record.
      * @param values A set of column_name/value pairs to update in the database.
      * @param selection An optional filter to match rows to update.
      * @return the number of rows affected.
      */
-    @Override
     public abstract int update(@NonNull Uri uri, @Nullable ContentValues values,
             @Nullable String selection, @Nullable String[] selectionArgs);
 
     /**
+     * Implement this to handle requests to update one or more rows. The
+     * implementation should update all rows matching the selection to set the
+     * columns according to the provided values map. As a courtesy, call
+     * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+     * notifyChange()} after updating. This method can be called from multiple
+     * threads, as described in <a href="
+     * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+     * and Threads</a>.
+     *
+     * @param uri The URI to query. This can potentially have a record ID if
+     *            this is an update request for a specific record.
+     * @param values A set of column_name/value pairs to update in the database.
+     * @param extras A Bundle containing all additional information necessary
+     *            for the update. Values in the Bundle may include SQL style
+     *            arguments.
+     * @return the number of rows affected.
+     */
+    @Override
+    public int update(@NonNull Uri uri, @Nullable ContentValues values,
+            @Nullable Bundle extras) {
+        extras = (extras != null) ? extras : Bundle.EMPTY;
+        return update(uri, values,
+                extras.getString(ContentResolver.QUERY_ARG_SQL_SELECTION),
+                extras.getStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS));
+    }
+
+    /**
      * Override this to handle requests to open a file blob.
      * The default implementation always throws {@link FileNotFoundException}.
      * This method can be called from multiple threads, as described in
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index d2632e7..bb65aa0 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -286,7 +286,7 @@
 
     /** See {@link ContentProvider#refresh} */
     @Override
-    public boolean refresh(Uri url, @Nullable Bundle args,
+    public boolean refresh(Uri url, @Nullable Bundle extras,
             @Nullable CancellationSignal cancellationSignal) throws RemoteException {
         Preconditions.checkNotNull(url, "url");
 
@@ -298,7 +298,7 @@
                 remoteCancellationSignal = mContentProvider.createCancellationSignal();
                 cancellationSignal.setRemote(remoteCancellationSignal);
             }
-            return mContentProvider.refresh(mPackageName, mFeatureId, url, args,
+            return mContentProvider.refresh(mPackageName, mFeatureId, url, extras,
                     remoteCancellationSignal);
         } catch (DeadObjectException e) {
             if (!mStable) {
@@ -331,14 +331,20 @@
     }
 
     /** See {@link ContentProvider#insert ContentProvider.insert} */
-    @Override
     public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues)
             throws RemoteException {
+        return insert(url, initialValues, null);
+    }
+
+    /** See {@link ContentProvider#insert ContentProvider.insert} */
+    @Override
+    public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues,
+            @Nullable Bundle extras) throws RemoteException {
         Preconditions.checkNotNull(url, "url");
 
         beforeRemote();
         try {
-            return mContentProvider.insert(mPackageName, mFeatureId, url, initialValues);
+            return mContentProvider.insert(mPackageName, mFeatureId, url, initialValues, extras);
         } catch (DeadObjectException e) {
             if (!mStable) {
                 mContentResolver.unstableProviderDied(mContentProvider);
@@ -370,15 +376,19 @@
     }
 
     /** See {@link ContentProvider#delete ContentProvider.delete} */
-    @Override
     public int delete(@NonNull Uri url, @Nullable String selection,
             @Nullable String[] selectionArgs) throws RemoteException {
+        return delete(url, ContentResolver.createSqlQueryBundle(selection, selectionArgs));
+    }
+
+    /** See {@link ContentProvider#delete ContentProvider.delete} */
+    @Override
+    public int delete(@NonNull Uri url, @Nullable Bundle extras) throws RemoteException {
         Preconditions.checkNotNull(url, "url");
 
         beforeRemote();
         try {
-            return mContentProvider.delete(mPackageName, mFeatureId, url, selection,
-                    selectionArgs);
+            return mContentProvider.delete(mPackageName, mFeatureId, url, extras);
         } catch (DeadObjectException e) {
             if (!mStable) {
                 mContentResolver.unstableProviderDied(mContentProvider);
@@ -390,15 +400,20 @@
     }
 
     /** See {@link ContentProvider#update ContentProvider.update} */
-    @Override
     public int update(@NonNull Uri url, @Nullable ContentValues values, @Nullable String selection,
             @Nullable String[] selectionArgs) throws RemoteException {
+        return update(url, values, ContentResolver.createSqlQueryBundle(selection, selectionArgs));
+    }
+
+    /** See {@link ContentProvider#update ContentProvider.update} */
+    @Override
+    public int update(@NonNull Uri url, @Nullable ContentValues values, @Nullable Bundle extras)
+            throws RemoteException {
         Preconditions.checkNotNull(url, "url");
 
         beforeRemote();
         try {
-            return mContentProvider.update(mPackageName, mFeatureId, url, values, selection,
-                    selectionArgs);
+            return mContentProvider.update(mPackageName, mFeatureId, url, values, extras);
         } catch (DeadObjectException e) {
             if (!mStable) {
                 mContentResolver.unstableProviderDied(mContentProvider);
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index f082690..dfa71f8 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -153,8 +153,9 @@
                     String featureId = data.readString();
                     Uri url = Uri.CREATOR.createFromParcel(data);
                     ContentValues values = ContentValues.CREATOR.createFromParcel(data);
+                    Bundle extras = data.readBundle();
 
-                    Uri out = insert(callingPkg, featureId, url, values);
+                    Uri out = insert(callingPkg, featureId, url, values, extras);
                     reply.writeNoException();
                     Uri.writeToParcel(reply, out);
                     return true;
@@ -199,10 +200,9 @@
                     String callingPkg = data.readString();
                     String featureId = data.readString();
                     Uri url = Uri.CREATOR.createFromParcel(data);
-                    String selection = data.readString();
-                    String[] selectionArgs = data.readStringArray();
+                    Bundle extras = data.readBundle();
 
-                    int count = delete(callingPkg, featureId, url, selection, selectionArgs);
+                    int count = delete(callingPkg, featureId, url, extras);
 
                     reply.writeNoException();
                     reply.writeInt(count);
@@ -216,11 +216,9 @@
                     String featureId = data.readString();
                     Uri url = Uri.CREATOR.createFromParcel(data);
                     ContentValues values = ContentValues.CREATOR.createFromParcel(data);
-                    String selection = data.readString();
-                    String[] selectionArgs = data.readStringArray();
+                    Bundle extras = data.readBundle();
 
-                    int count = update(callingPkg, featureId, url, values, selection,
-                            selectionArgs);
+                    int count = update(callingPkg, featureId, url, values, extras);
 
                     reply.writeNoException();
                     reply.writeInt(count);
@@ -283,10 +281,10 @@
                     String authority = data.readString();
                     String method = data.readString();
                     String stringArg = data.readString();
-                    Bundle args = data.readBundle();
+                    Bundle extras = data.readBundle();
 
                     Bundle responseBundle = call(callingPkg, featureId, authority, method,
-                            stringArg, args);
+                            stringArg, extras);
 
                     reply.writeNoException();
                     reply.writeBundle(responseBundle);
@@ -370,11 +368,11 @@
                     String callingPkg = data.readString();
                     String featureId = data.readString();
                     Uri url = Uri.CREATOR.createFromParcel(data);
-                    Bundle args = data.readBundle();
+                    Bundle extras = data.readBundle();
                     ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
                             data.readStrongBinder());
 
-                    boolean out = refresh(callingPkg, featureId, url, args, signal);
+                    boolean out = refresh(callingPkg, featureId, url, extras, signal);
                     reply.writeNoException();
                     reply.writeInt(out ? 0 : -1);
                     return true;
@@ -498,7 +496,7 @@
 
     @Override
     public Uri insert(String callingPkg, @Nullable String featureId, Uri url,
-            ContentValues values) throws RemoteException
+            ContentValues values, Bundle extras) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -509,6 +507,7 @@
             data.writeString(featureId);
             url.writeToParcel(data, 0);
             values.writeToParcel(data, 0);
+            data.writeBundle(extras);
 
             mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);
 
@@ -573,8 +572,8 @@
     }
 
     @Override
-    public int delete(String callingPkg, @Nullable String featureId, Uri url, String selection,
-            String[] selectionArgs) throws RemoteException {
+    public int delete(String callingPkg, @Nullable String featureId, Uri url, Bundle extras)
+            throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
@@ -583,8 +582,7 @@
             data.writeString(callingPkg);
             data.writeString(featureId);
             url.writeToParcel(data, 0);
-            data.writeString(selection);
-            data.writeStringArray(selectionArgs);
+            data.writeBundle(extras);
 
             mRemote.transact(IContentProvider.DELETE_TRANSACTION, data, reply, 0);
 
@@ -599,7 +597,7 @@
 
     @Override
     public int update(String callingPkg, @Nullable String featureId, Uri url,
-            ContentValues values, String selection, String[] selectionArgs) throws RemoteException {
+            ContentValues values, Bundle extras) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
@@ -609,8 +607,7 @@
             data.writeString(featureId);
             url.writeToParcel(data, 0);
             values.writeToParcel(data, 0);
-            data.writeString(selection);
-            data.writeStringArray(selectionArgs);
+            data.writeBundle(extras);
 
             mRemote.transact(IContentProvider.UPDATE_TRANSACTION, data, reply, 0);
 
@@ -682,7 +679,7 @@
 
     @Override
     public Bundle call(String callingPkg, @Nullable String featureId, String authority,
-            String method, String request, Bundle args) throws RemoteException {
+            String method, String request, Bundle extras) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
@@ -693,7 +690,7 @@
             data.writeString(authority);
             data.writeString(method);
             data.writeString(request);
-            data.writeBundle(args);
+            data.writeBundle(extras);
 
             mRemote.transact(IContentProvider.CALL_TRANSACTION, data, reply, 0);
 
@@ -824,7 +821,7 @@
     }
 
     @Override
-    public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle args,
+    public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle extras,
             ICancellationSignal signal) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -834,7 +831,7 @@
             data.writeString(callingPkg);
             data.writeString(featureId);
             url.writeToParcel(data, 0);
-            data.writeBundle(args);
+            data.writeBundle(extras);
             data.writeStrongBinder(signal != null ? signal.asBinder() : null);
 
             mRemote.transact(IContentProvider.REFRESH_TRANSACTION, data, reply, 0);
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 5c2de57..93f4287 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -357,11 +357,22 @@
             ContentProviderResult[] backRefs, int numBackRefs)
             throws OperationApplicationException {
         final ContentValues values = resolveValueBackReferences(backRefs, numBackRefs);
-        final Bundle extras = resolveExtrasBackReferences(backRefs, numBackRefs);
-        final String[] selectionArgs = resolveSelectionArgsBackReferences(backRefs, numBackRefs);
+
+        // If the creator requested explicit selection or selectionArgs, it
+        // should take precedence over similar values they defined in extras
+        Bundle extras = resolveExtrasBackReferences(backRefs, numBackRefs);
+        if (mSelection != null) {
+            extras = (extras != null) ? extras : new Bundle();
+            extras.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, mSelection);
+        }
+        if (mSelectionArgs != null) {
+            extras = (extras != null) ? extras : new Bundle();
+            extras.putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS,
+                    resolveSelectionArgsBackReferences(backRefs, numBackRefs));
+        }
 
         if (mType == TYPE_INSERT) {
-            final Uri newUri = provider.insert(mUri, values);
+            final Uri newUri = provider.insert(mUri, values, extras);
             if (newUri != null) {
                 return new ContentProviderResult(newUri);
             } else {
@@ -375,9 +386,9 @@
 
         final int numRows;
         if (mType == TYPE_DELETE) {
-            numRows = provider.delete(mUri, mSelection, selectionArgs);
+            numRows = provider.delete(mUri, extras);
         } else if (mType == TYPE_UPDATE) {
-            numRows = provider.update(mUri, values, mSelection, selectionArgs);
+            numRows = provider.update(mUri, values, extras);
         } else if (mType == TYPE_ASSERT) {
             // Assert that all rows match expected values
             String[] projection =  null;
@@ -389,7 +400,7 @@
                 }
                 projection = projectionList.toArray(new String[projectionList.size()]);
             }
-            final Cursor cursor = provider.query(mUri, projection, mSelection, selectionArgs, null);
+            final Cursor cursor = provider.query(mUri, projection, extras, null);
             try {
                 numRows = cursor.getCount();
                 if (projection != null) {
@@ -1013,6 +1024,10 @@
 
         private void assertExtrasAllowed() {
             switch (mType) {
+                case TYPE_INSERT:
+                case TYPE_UPDATE:
+                case TYPE_DELETE:
+                case TYPE_ASSERT:
                 case TYPE_CALL:
                     break;
                 default:
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 61c8db5d..d4280f8 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -304,31 +304,61 @@
      */
     public static final String QUERY_ARG_SQL_SORT_ORDER = "android:query-arg-sql-sort-order";
 
-    /** {@hide} */
+    /**
+     * Key for an SQL style {@code GROUP BY} string that may be present in the
+     * query Bundle argument passed to
+     * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}.
+     *
+     * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly
+     * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b>
+     *
+     * @see #QUERY_ARG_GROUP_COLUMNS
+     */
     public static final String QUERY_ARG_SQL_GROUP_BY = "android:query-arg-sql-group-by";
-    /** {@hide} */
+
+    /**
+     * Key for an SQL style {@code HAVING} string that may be present in the
+     * query Bundle argument passed to
+     * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}.
+     *
+     * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly
+     * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b>
+     */
     public static final String QUERY_ARG_SQL_HAVING = "android:query-arg-sql-having";
-    /** {@hide} */
+
+    /**
+     * Key for an SQL style {@code LIMIT} string that may be present in the
+     * query Bundle argument passed to
+     * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}.
+     *
+     * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly
+     * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b>
+     *
+     * @see #QUERY_ARG_LIMIT
+     * @see #QUERY_ARG_OFFSET
+     */
     public static final String QUERY_ARG_SQL_LIMIT = "android:query-arg-sql-limit";
 
     /**
-     * Specifies the list of columns against which to sort results. When first column values
-     * are identical, records are then sorted based on second column values, and so on.
-     *
-     * <p>Columns present in this list must also be included in the projection
-     * supplied to {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
-     *
-     * <p>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher:
-     *
+     * Specifies the list of columns (stored as a {@code String[]}) against
+     * which to sort results. When first column values are identical, records
+     * are then sorted based on second column values, and so on.
+     * <p>
+     * Columns present in this list must also be included in the projection
+     * supplied to
+     * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
+     * <p>
+     * Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher:
      * <li>{@link ContentProvider} implementations: When preparing data in
-     * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}, if sort columns
-     * is reflected in the returned Cursor, it is  strongly recommended that
-     * {@link #QUERY_ARG_SORT_COLUMNS} then be included in the array of honored arguments
-     * reflected in {@link Cursor} extras {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
-     *
-     * <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in the
-     * arguments {@link Bundle}, the Content framework will attempt to synthesize
-     * an QUERY_ARG_SQL* argument using the corresponding QUERY_ARG_SORT* values.
+     * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)},
+     * if sort columns is reflected in the returned Cursor, it is strongly
+     * recommended that {@link #QUERY_ARG_SORT_COLUMNS} then be included in the
+     * array of honored arguments reflected in {@link Cursor} extras
+     * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
+     * <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in
+     * the arguments {@link Bundle}, the Content framework will attempt to
+     * synthesize an QUERY_ARG_SQL* argument using the corresponding
+     * QUERY_ARG_SORT* values.
      */
     public static final String QUERY_ARG_SORT_COLUMNS = "android:query-arg-sort-columns";
 
@@ -402,6 +432,29 @@
     public static final String QUERY_ARG_SORT_LOCALE = "android:query-arg-sort-locale";
 
     /**
+     * Specifies the list of columns (stored as a {@code String[]}) against
+     * which to group results. When column values are identical, multiple
+     * records are collapsed together into a single record.
+     * <p>
+     * Columns present in this list must also be included in the projection
+     * supplied to
+     * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
+     * <p>
+     * Apps targeting {@link android.os.Build.VERSION_CODES#R} or higher:
+     * <li>{@link ContentProvider} implementations: When preparing data in
+     * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)},
+     * if group columns is reflected in the returned Cursor, it is strongly
+     * recommended that {@link #QUERY_ARG_SORT_COLUMNS} then be included in the
+     * array of honored arguments reflected in {@link Cursor} extras
+     * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
+     * <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in
+     * the arguments {@link Bundle}, the Content framework will attempt to
+     * synthesize an QUERY_ARG_SQL* argument using the corresponding
+     * QUERY_ARG_SORT* values.
+     */
+    public static final String QUERY_ARG_GROUP_COLUMNS = "android:query-arg-group-columns";
+
+    /**
      * Allows provider to report back to client which query keys are honored in a Cursor.
      *
      * <p>Key identifying a {@code String[]} containing all QUERY_ARG_SORT* arguments
@@ -415,6 +468,7 @@
      * @see #QUERY_ARG_SORT_DIRECTION
      * @see #QUERY_ARG_SORT_COLLATION
      * @see #QUERY_ARG_SORT_LOCALE
+     * @see #QUERY_ARG_GROUP_COLUMNS
      */
     public static final String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS";
 
@@ -1127,28 +1181,31 @@
     }
 
     /**
-     * This allows clients to request an explicit refresh of content identified by {@code uri}.
+     * This allows clients to request an explicit refresh of content identified
+     * by {@code uri}.
      * <p>
-     * Client code should only invoke this method when there is a strong indication (such as a user
-     * initiated pull to refresh gesture) that the content is stale.
+     * Client code should only invoke this method when there is a strong
+     * indication (such as a user initiated pull to refresh gesture) that the
+     * content is stale.
      * <p>
      *
      * @param url The Uri identifying the data to refresh.
-     * @param args Additional options from the client. The definitions of these are specific to the
-     *            content provider being called.
-     * @param cancellationSignal A signal to cancel the operation in progress, or {@code null} if
-     *            none. For example, if you called refresh on a particular uri, you should call
-     *            {@link CancellationSignal#throwIfCanceled()} to check whether the client has
-     *            canceled the refresh request.
+     * @param extras Additional options from the client. The definitions of
+     *            these are specific to the content provider being called.
+     * @param cancellationSignal A signal to cancel the operation in progress,
+     *            or {@code null} if none. For example, if you called refresh on
+     *            a particular uri, you should call
+     *            {@link CancellationSignal#throwIfCanceled()} to check whether
+     *            the client has canceled the refresh request.
      * @return true if the provider actually tried refreshing.
      */
     @Override
-    public final boolean refresh(@NonNull Uri url, @Nullable Bundle args,
+    public final boolean refresh(@NonNull Uri url, @Nullable Bundle extras,
             @Nullable CancellationSignal cancellationSignal) {
         Preconditions.checkNotNull(url, "url");
 
         try {
-            if (mWrapped != null) return mWrapped.refresh(url, args, cancellationSignal);
+            if (mWrapped != null) return mWrapped.refresh(url, extras, cancellationSignal);
         } catch (RemoteException e) {
             return false;
         }
@@ -1165,7 +1222,7 @@
                 remoteCancellationSignal = provider.createCancellationSignal();
                 cancellationSignal.setRemote(remoteCancellationSignal);
             }
-            return provider.refresh(mPackageName, mFeatureId, url, args,
+            return provider.refresh(mPackageName, mFeatureId, url, extras,
                     remoteCancellationSignal);
         } catch (RemoteException e) {
             // Arbitrary and not worth documenting, as Activity
@@ -1856,13 +1913,30 @@
      * @return the URL of the newly created row. May return <code>null</code> if the underlying
      *         content provider returns <code>null</code>, or if it crashes.
      */
-    @Override
     public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
                 @Nullable ContentValues values) {
+        return insert(url, values, null);
+    }
+
+    /**
+     * Inserts a row into a table at the given URL.
+     *
+     * If the content provider supports transactions the insertion will be atomic.
+     *
+     * @param url The URL of the table to insert into.
+     * @param values The initial values for the newly inserted row. The key is the column name for
+     *               the field. Passing an empty ContentValues will create an empty row.
+     * @param extras A Bundle containing all additional information necessary for the insert.
+     * @return the URL of the newly created row. May return <code>null</code> if the underlying
+     *         content provider returns <code>null</code>, or if it crashes.
+     */
+    @Override
+    public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
+            @Nullable ContentValues values, @Nullable Bundle extras) {
         Preconditions.checkNotNull(url, "url");
 
         try {
-            if (mWrapped != null) return mWrapped.insert(url, values);
+            if (mWrapped != null) return mWrapped.insert(url, values, extras);
         } catch (RemoteException e) {
             return null;
         }
@@ -1873,7 +1947,7 @@
         }
         try {
             long startTime = SystemClock.uptimeMillis();
-            Uri createdRow = provider.insert(mPackageName, mFeatureId, url, values);
+            Uri createdRow = provider.insert(mPackageName, mFeatureId, url, values, extras);
             long durationMillis = SystemClock.uptimeMillis() - startTime;
             maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
             return createdRow;
@@ -1977,13 +2051,27 @@
                     (excluding the WHERE itself).
      * @return The number of rows deleted.
      */
-    @Override
     public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable String where,
             @Nullable String[] selectionArgs) {
+        return delete(url, createSqlQueryBundle(where, selectionArgs));
+    }
+
+    /**
+     * Deletes row(s) specified by a content URI.
+     *
+     * If the content provider supports transactions, the deletion will be atomic.
+     *
+     * @param url The URL of the row to delete.
+     * @param extras A Bundle containing all additional information necessary for the delete.
+     *            Values in the Bundle may include SQL style arguments.
+     * @return The number of rows deleted.
+     */
+    @Override
+    public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable Bundle extras) {
         Preconditions.checkNotNull(url, "url");
 
         try {
-            if (mWrapped != null) return mWrapped.delete(url, where, selectionArgs);
+            if (mWrapped != null) return mWrapped.delete(url, extras);
         } catch (RemoteException e) {
             return 0;
         }
@@ -1994,10 +2082,9 @@
         }
         try {
             long startTime = SystemClock.uptimeMillis();
-            int rowsDeleted = provider.delete(mPackageName, mFeatureId, url, where,
-                    selectionArgs);
+            int rowsDeleted = provider.delete(mPackageName, mFeatureId, url, extras);
             long durationMillis = SystemClock.uptimeMillis() - startTime;
-            maybeLogUpdateToEventLog(durationMillis, url, "delete", where);
+            maybeLogUpdateToEventLog(durationMillis, url, "delete", null);
             return rowsDeleted;
         } catch (RemoteException e) {
             // Arbitrary and not worth documenting, as Activity
@@ -2021,14 +2108,32 @@
      * @return the number of rows updated.
      * @throws NullPointerException if uri or values are null
      */
-    @Override
     public final int update(@RequiresPermission.Write @NonNull Uri uri,
             @Nullable ContentValues values, @Nullable String where,
             @Nullable String[] selectionArgs) {
+        return update(uri, values, createSqlQueryBundle(where, selectionArgs));
+    }
+
+    /**
+     * Update row(s) in a content URI.
+     *
+     * If the content provider supports transactions the update will be atomic.
+     *
+     * @param uri The URI to modify.
+     * @param values The new field values. The key is the column name for the field.
+                     A null value will remove an existing field value.
+     * @param extras A Bundle containing all additional information necessary for the update.
+     *            Values in the Bundle may include SQL style arguments.
+     * @return the number of rows updated.
+     * @throws NullPointerException if uri or values are null
+     */
+    @Override
+    public final int update(@RequiresPermission.Write @NonNull Uri uri,
+            @Nullable ContentValues values, @Nullable Bundle extras) {
         Preconditions.checkNotNull(uri, "uri");
 
         try {
-            if (mWrapped != null) return mWrapped.update(uri, values, where, selectionArgs);
+            if (mWrapped != null) return mWrapped.update(uri, values, extras);
         } catch (RemoteException e) {
             return 0;
         }
@@ -2039,10 +2144,9 @@
         }
         try {
             long startTime = SystemClock.uptimeMillis();
-            int rowsUpdated = provider.update(mPackageName, mFeatureId, uri, values, where,
-                    selectionArgs);
+            int rowsUpdated = provider.update(mPackageName, mFeatureId, uri, values, extras);
             long durationMillis = SystemClock.uptimeMillis() - startTime;
-            maybeLogUpdateToEventLog(durationMillis, uri, "update", where);
+            maybeLogUpdateToEventLog(durationMillis, uri, "update", null);
             return rowsUpdated;
         } catch (RemoteException e) {
             // Arbitrary and not worth documenting, as Activity
@@ -3589,6 +3693,15 @@
      */
     public static @Nullable Bundle createSqlQueryBundle(
             @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        return createSqlQueryBundle(selection, selectionArgs, null);
+    }
+
+    /**
+     * @hide
+     */
+    public static @Nullable Bundle createSqlQueryBundle(
+            @Nullable String selection,
             @Nullable String[] selectionArgs,
             @Nullable String sortOrder) {
 
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index d2c97c4..1fb2958 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -48,10 +48,10 @@
             + "instead")
     public default Uri insert(String callingPkg, Uri url, ContentValues initialValues)
             throws RemoteException {
-        return insert(callingPkg, null, url, initialValues);
+        return insert(callingPkg, null, url, initialValues, null);
     }
-    public Uri insert(String callingPkg, String featureId, Uri url, ContentValues initialValues)
-            throws RemoteException;
+    public Uri insert(String callingPkg, String featureId, Uri url, ContentValues initialValues,
+            Bundle extras) throws RemoteException;
     @Deprecated
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
             + "ContentProviderClient#bulkInsert(android.net.Uri, android.content.ContentValues[])"
@@ -68,20 +68,22 @@
             + ".String[])} instead")
     public default int delete(String callingPkg, Uri url, String selection, String[] selectionArgs)
             throws RemoteException {
-        return delete(callingPkg, null, url, selection, selectionArgs);
+        return delete(callingPkg, null, url,
+                ContentResolver.createSqlQueryBundle(selection, selectionArgs));
     }
-    public int delete(String callingPkg, String featureId, Uri url, String selection,
-            String[] selectionArgs) throws RemoteException;
+    public int delete(String callingPkg, String featureId, Uri url, Bundle extras)
+            throws RemoteException;
     @Deprecated
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
             + "ContentProviderClient#update(android.net.Uri, android.content.ContentValues, java"
             + ".lang.String, java.lang.String[])} instead")
     public default int update(String callingPkg, Uri url, ContentValues values, String selection,
             String[] selectionArgs) throws RemoteException {
-        return update(callingPkg, null, url, values, selection, selectionArgs);
+        return update(callingPkg, null, url, values,
+                ContentResolver.createSqlQueryBundle(selection, selectionArgs));
     }
     public int update(String callingPkg, String featureId, Uri url, ContentValues values,
-            String selection, String[] selectionArgs) throws RemoteException;
+            Bundle extras) throws RemoteException;
 
     public ParcelFileDescriptor openFile(String callingPkg, @Nullable String featureId, Uri url,
             String mode, ICancellationSignal signal, IBinder callerToken)
@@ -119,7 +121,7 @@
             throws RemoteException;
 
     public boolean refresh(String callingPkg, @Nullable String featureId, Uri url,
-            @Nullable Bundle args, ICancellationSignal cancellationSignal) throws RemoteException;
+            @Nullable Bundle extras, ICancellationSignal cancellationSignal) throws RemoteException;
 
     // Data interchange.
     public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException;
diff --git a/core/java/android/content/LoggingContentInterface.java b/core/java/android/content/LoggingContentInterface.java
index 1df1c4f..3bd0832 100644
--- a/core/java/android/content/LoggingContentInterface.java
+++ b/core/java/android/content/LoggingContentInterface.java
@@ -178,11 +178,11 @@
     }
 
     @Override
-    public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues)
-            throws RemoteException {
-        try (Logger l = new Logger("insert", uri, initialValues)) {
+    public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues,
+            @Nullable Bundle extras) throws RemoteException {
+        try (Logger l = new Logger("insert", uri, initialValues, extras)) {
             try {
-                return l.setResult(delegate.insert(uri, initialValues));
+                return l.setResult(delegate.insert(uri, initialValues, extras));
             } catch (Exception res) {
                 l.setResult(res);
                 throw res;
@@ -204,11 +204,10 @@
     }
 
     @Override
-    public int delete(@NonNull Uri uri, @Nullable String selection,
-            @Nullable String[] selectionArgs) throws RemoteException {
-        try (Logger l = new Logger("delete", uri, selection, selectionArgs)) {
+    public int delete(@NonNull Uri uri, @Nullable Bundle extras) throws RemoteException {
+        try (Logger l = new Logger("delete", uri, extras)) {
             try {
-                return l.setResult(delegate.delete(uri, selection, selectionArgs));
+                return l.setResult(delegate.delete(uri, extras));
             } catch (Exception res) {
                 l.setResult(res);
                 throw res;
@@ -217,11 +216,11 @@
     }
 
     @Override
-    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
-            @Nullable String[] selectionArgs) throws RemoteException {
-        try (Logger l = new Logger("update", uri, values, selection, selectionArgs)) {
+    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable Bundle extras)
+            throws RemoteException {
+        try (Logger l = new Logger("update", uri, values, extras)) {
             try {
-                return l.setResult(delegate.update(uri, values, selection, selectionArgs));
+                return l.setResult(delegate.update(uri, values, extras));
             } catch (Exception res) {
                 l.setResult(res);
                 throw res;
diff --git a/core/java/android/hardware/display/BrightnessChangeEvent.java b/core/java/android/hardware/display/BrightnessChangeEvent.java
index 21fcc63..a6a44be 100644
--- a/core/java/android/hardware/display/BrightnessChangeEvent.java
+++ b/core/java/android/hardware/display/BrightnessChangeEvent.java
@@ -79,7 +79,8 @@
     /**
      * Histogram counting how many times a pixel of a given value was displayed onscreen for the
      * Value component of HSV if the device supports color sampling, if the device does not support
-     * color sampling the value will be null.
+     * color sampling or {@link BrightnessConfiguration#shouldCollectColorSamples()} is false the
+     * value will be null.
      *
      * The buckets of the histogram are evenly weighted, the number of buckets is device specific.
      * The units are in pixels * milliseconds, with 1 pixel millisecond being 1 pixel displayed
@@ -94,7 +95,8 @@
 
     /**
      * How many milliseconds of data are contained in the colorValueBuckets, if the device does
-     * not support color sampling the value will be 0L.
+     * not support color sampling or {@link BrightnessConfiguration#shouldCollectColorSamples()} is
+     * false the value will be 0L.
      *
      * {@see #colorValueBuckets}
      */
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index 4c2e297..139be8e 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -49,26 +49,31 @@
     private static final String TAG_BRIGHTNESS_POINT = "brightness-point";
     private static final String TAG_BRIGHTNESS_CORRECTIONS = "brightness-corrections";
     private static final String TAG_BRIGHTNESS_CORRECTION = "brightness-correction";
+    private static final String TAG_BRIGHTNESS_PARAMS = "brightness-params";
     private static final String ATTR_LUX = "lux";
     private static final String ATTR_NITS = "nits";
     private static final String ATTR_DESCRIPTION = "description";
     private static final String ATTR_PACKAGE_NAME = "package-name";
     private static final String ATTR_CATEGORY = "category";
+    private static final String ATTR_COLLECT_COLOR = "collect-color";
 
     private final float[] mLux;
     private final float[] mNits;
     private final Map<String, BrightnessCorrection> mCorrectionsByPackageName;
     private final Map<Integer, BrightnessCorrection> mCorrectionsByCategory;
     private final String mDescription;
+    private final boolean mShouldCollectColorSamples;
 
     private BrightnessConfiguration(float[] lux, float[] nits,
             Map<String, BrightnessCorrection> correctionsByPackageName,
-            Map<Integer, BrightnessCorrection> correctionsByCategory, String description) {
+            Map<Integer, BrightnessCorrection> correctionsByCategory, String description,
+            boolean shouldCollectColorSamples) {
         mLux = lux;
         mNits = nits;
         mCorrectionsByPackageName = correctionsByPackageName;
         mCorrectionsByCategory = correctionsByCategory;
         mDescription = description;
+        mShouldCollectColorSamples = shouldCollectColorSamples;
     }
 
     /**
@@ -119,6 +124,14 @@
         return mDescription;
     }
 
+    /**
+     * Returns whether color samples should be collected in
+     * {@link BrightnessChangeEvent#colorValueBuckets}.
+     */
+    public boolean shouldCollectColorSamples() {
+        return mShouldCollectColorSamples;
+    }
+
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeFloatArray(mLux);
@@ -138,6 +151,7 @@
             correction.writeToParcel(dest, flags);
         }
         dest.writeString(mDescription);
+        dest.writeBoolean(mShouldCollectColorSamples);
     }
 
     @Override
@@ -167,6 +181,7 @@
         if (mDescription != null) {
             sb.append(mDescription);
         }
+        sb.append(", shouldCollectColorSamples = " + mShouldCollectColorSamples);
         sb.append("'}");
         return sb.toString();
     }
@@ -181,6 +196,7 @@
         if (mDescription != null) {
             result = result * 31 + mDescription.hashCode();
         }
+        result = result * 31 + Boolean.hashCode(mShouldCollectColorSamples);
         return result;
     }
 
@@ -196,7 +212,8 @@
         return Arrays.equals(mLux, other.mLux) && Arrays.equals(mNits, other.mNits)
                 && mCorrectionsByPackageName.equals(other.mCorrectionsByPackageName)
                 && mCorrectionsByCategory.equals(other.mCorrectionsByCategory)
-                && Objects.equals(mDescription, other.mDescription);
+                && Objects.equals(mDescription, other.mDescription)
+                && mShouldCollectColorSamples == other.mShouldCollectColorSamples;
     }
 
     public static final @android.annotation.NonNull Creator<BrightnessConfiguration> CREATOR =
@@ -224,6 +241,8 @@
 
             final String description = in.readString();
             builder.setDescription(description);
+            final boolean shouldCollectColorSamples = in.readBoolean();
+            builder.setShouldCollectColorSamples(shouldCollectColorSamples);
             return builder.build();
         }
 
@@ -252,6 +271,7 @@
             serializer.endTag(null, TAG_BRIGHTNESS_POINT);
         }
         serializer.endTag(null, TAG_BRIGHTNESS_CURVE);
+
         serializer.startTag(null, TAG_BRIGHTNESS_CORRECTIONS);
         for (Map.Entry<String, BrightnessCorrection> entry :
                 mCorrectionsByPackageName.entrySet()) {
@@ -271,6 +291,12 @@
             serializer.endTag(null, TAG_BRIGHTNESS_CORRECTION);
         }
         serializer.endTag(null, TAG_BRIGHTNESS_CORRECTIONS);
+
+        serializer.startTag(null, TAG_BRIGHTNESS_PARAMS);
+        if (mShouldCollectColorSamples) {
+            serializer.attribute(null, ATTR_COLLECT_COLOR, Boolean.toString(true));
+        }
+        serializer.endTag(null, TAG_BRIGHTNESS_PARAMS);
     }
 
     /**
@@ -293,6 +319,7 @@
         List<Float> nitsList = new ArrayList<>();
         Map<String, BrightnessCorrection> correctionsByPackageName = new HashMap<>();
         Map<Integer, BrightnessCorrection> correctionsByCategory = new HashMap<>();
+        boolean shouldCollectColorSamples = false;
         final int configDepth = parser.getDepth();
         while (XmlUtils.nextElementWithin(parser, configDepth)) {
             if (TAG_BRIGHTNESS_CURVE.equals(parser.getName())) {
@@ -307,8 +334,7 @@
                     luxList.add(lux);
                     nitsList.add(nits);
                 }
-            }
-            if (TAG_BRIGHTNESS_CORRECTIONS.equals(parser.getName())) {
+            } else if (TAG_BRIGHTNESS_CORRECTIONS.equals(parser.getName())) {
                 final int correctionsDepth = parser.getDepth();
                 while (XmlUtils.nextElementWithin(parser, correctionsDepth)) {
                     if (!TAG_BRIGHTNESS_CORRECTION.equals(parser.getName())) {
@@ -328,6 +354,9 @@
                         }
                     }
                 }
+            } else if (TAG_BRIGHTNESS_PARAMS.equals(parser.getName())) {
+                shouldCollectColorSamples =
+                        Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_COLLECT_COLOR));
             }
         }
         final int n = luxList.size();
@@ -350,6 +379,7 @@
             final BrightnessCorrection correction = entry.getValue();
             builder.addCorrectionByCategory(category, correction);
         }
+        builder.setShouldCollectColorSamples(shouldCollectColorSamples);
         return builder.build();
     }
 
@@ -374,6 +404,7 @@
         private Map<String, BrightnessCorrection> mCorrectionsByPackageName;
         private Map<Integer, BrightnessCorrection> mCorrectionsByCategory;
         private String mDescription;
+        private boolean mShouldCollectColorSamples;
 
         /**
          * Constructs the builder with the control points for the brightness curve.
@@ -498,6 +529,19 @@
         }
 
         /**
+         * Control whether screen color samples should be returned in
+         * {@link BrightnessChangeEvent#colorValueBuckets} if supported by the device.
+         *
+         * @param shouldCollectColorSamples true if color samples should be collected.
+         * @return
+         */
+        @NonNull
+        public Builder setShouldCollectColorSamples(boolean shouldCollectColorSamples) {
+            mShouldCollectColorSamples = shouldCollectColorSamples;
+            return this;
+        }
+
+        /**
          * Builds the {@link BrightnessConfiguration}.
          */
         @NonNull
@@ -506,7 +550,7 @@
                 throw new IllegalStateException("A curve must be set!");
             }
             return new BrightnessConfiguration(mCurveLux, mCurveNits, mCorrectionsByPackageName,
-                    mCorrectionsByCategory, mDescription);
+                    mCorrectionsByCategory, mDescription, mShouldCollectColorSamples);
         }
 
         private static void checkMonotonic(float[] vals, boolean strictlyIncreasing, String name) {
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index 5bc9953..990c114 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -25,6 +25,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.util.Preconditions;
+
 import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.List;
@@ -152,6 +154,7 @@
          * @return The {@link Builder} for chaining.
          */
         public @NonNull Builder setDnsServers(@NonNull Iterable<InetAddress> dnsServers) {
+            Preconditions.checkNotNull(dnsServers);
             mDnsServers = dnsServers;
             return this;
         }
@@ -175,8 +178,10 @@
             final StaticIpConfiguration config = new StaticIpConfiguration();
             config.ipAddress = mIpAddress;
             config.gateway = mGateway;
-            for (InetAddress server : mDnsServers) {
-                config.dnsServers.add(server);
+            if (mDnsServers != null) {
+                for (InetAddress server : mDnsServers) {
+                    config.dnsServers.add(server);
+                }
             }
             config.domains = mDomains;
             return config;
diff --git a/core/java/android/net/util/MultinetworkPolicyTracker.java b/core/java/android/net/util/MultinetworkPolicyTracker.java
index 4e88149..aa0f622 100644
--- a/core/java/android/net/util/MultinetworkPolicyTracker.java
+++ b/core/java/android/net/util/MultinetworkPolicyTracker.java
@@ -94,7 +94,8 @@
             }
         };
 
-        TelephonyManager.from(ctx).listen(new PhoneStateListener(handler.getLooper()) {
+        ctx.getSystemService(TelephonyManager.class).listen(
+                new PhoneStateListener(handler.getLooper()) {
             @Override
             public void onActiveDataSubscriptionIdChanged(int subId) {
                 mActiveSubId = subId;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index ed21b72..bb62eb2 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1359,8 +1359,11 @@
                 mContext.getContentResolver(),
                 Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, 0) != 0;
         boolean isSystemUserUnlocked = isUserUnlocked(UserHandle.SYSTEM);
-        boolean inCall = TelephonyManager.getDefault().getCallState()
-                != TelephonyManager.CALL_STATE_IDLE;
+        boolean inCall = false;
+        TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
+        if (telephonyManager != null) {
+            inCall = telephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE;
+        }
         boolean isUserSwitchDisallowed = hasUserRestriction(DISALLOW_USER_SWITCH);
         return (allowUserSwitchingWhenSystemUserLocked || isSystemUserUnlocked) && !inCall
                 && !isUserSwitchDisallowed;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 50dac46..3ac7deb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -14099,6 +14099,77 @@
                 "android.settings.panel.action.VOLUME";
     }
 
+    /**
+     * Activity Action: Show setting page to process the addition of Wi-Fi networks to the user's
+     * saved network list. The app should send a new intent with an extra that holds a maximum of
+     * five {@link android.net.wifi.WifiConfiguration} that specify credentials for the networks to
+     * be added to the user's database. The Intent should be sent via the {@link
+     * android.app.Activity#startActivityForResult(Intent, int)} API.
+     * <p>
+     * Note: The app sending the Intent to add the credentials doesn't get any ownership over the
+     * newly added network(s). For the Wi-Fi stack, these networks will look like the user
+     * manually added them from the Settings UI.
+     * <p>
+     * Input: The app should put parcelable array list to
+     * {@link android.net.wifi.WifiConfiguration} into the
+     * {@link #EXTRA_WIFI_CONFIGURATION_LIST} extra.
+     * <p>
+     * Output: After {@link android.app.Activity#startActivityForResult(Intent, int)}, the
+     * callback {@link android.app.Activity#onActivityResult(int, int, Intent)} will have a
+     * result code {@link android.app.Activity#RESULT_OK} to indicate user pressed the save
+     * button to save the networks or {@link android.app.Activity#RESULT_CANCELED} to indicate
+     * that the user rejected the request. Additionally, an integer array list, stored in
+     * {@link #EXTRA_WIFI_CONFIGURATION_RESULT_LIST}, will indicate the process result of
+     * each network.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_WIFI_ADD_NETWORKS =
+            "android.settings.WIFI_ADD_NETWORKS";
+
+    /**
+     * A bundle extra of {@link #ACTION_WIFI_ADD_NETWORKS} intent action that indicates all the
+     * {@link android.net.wifi.WifiConfiguration} that would be saved.
+     */
+    public static final String EXTRA_WIFI_CONFIGURATION_LIST =
+            "android.provider.extra.WIFI_CONFIGURATION_LIST";
+
+    /**
+     * A bundle extra of the result of {@link #ACTION_WIFI_ADD_NETWORKS} intent action that
+     * indicates the action result of the saved {@link android.net.wifi.WifiConfiguration}. It's
+     * value of AddWifiResult interface, and will be 1:1 mapping to the element in {@link
+     * #EXTRA_WIFI_CONFIGURATION_LIST}.
+     */
+    public static final String EXTRA_WIFI_CONFIGURATION_RESULT_LIST =
+            "android.provider.extra.WIFI_CONFIGURATION_RESULT_LIST";
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"ADD_WIFI_RESULT_"}, value = {
+            ADD_WIFI_RESULT_SUCCESS,
+            ADD_WIFI_RESULT_ADD_OR_UPDATE_FAILED,
+            ADD_WIFI_RESULT_ALREADY_EXISTS
+    })
+    public @interface AddWifiResult {
+    }
+
+    /**
+     * A result of {@link #ACTION_WIFI_ADD_NETWORKS} intent action that saving or updating the
+     * corresponding Wi-Fi network was successful.
+     */
+    public static final int ADD_WIFI_RESULT_SUCCESS = 0;
+
+    /**
+     * A result of {@link #ACTION_WIFI_ADD_NETWORKS} intent action that saving the corresponding
+     * Wi-Fi network failed.
+     */
+    public static final int ADD_WIFI_RESULT_ADD_OR_UPDATE_FAILED = 1;
+
+    /**
+     * A result of {@link #ACTION_WIFI_ADD_NETWORKS} intent action that indicates the Wi-Fi network
+     * already exists.
+     */
+    public static final int ADD_WIFI_RESULT_ALREADY_EXISTS = 2;
+
     private static final String[] PM_WRITE_SETTINGS = {
         android.Manifest.permission.WRITE_SETTINGS
     };
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index df54209..993bbe8 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -663,11 +663,8 @@
     private static void gatherTelLinks(ArrayList<LinkSpec> links, Spannable s,
             @Nullable Context context) {
         PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
-        final TelephonyManager tm = (context == null)
-                ? TelephonyManager.getDefault()
-                : TelephonyManager.from(context);
         Iterable<PhoneNumberMatch> matches = phoneUtil.findNumbers(s.toString(),
-                tm.getSimCountryIso().toUpperCase(Locale.US),
+                TelephonyManager.getDefaultSimCountryIso().toUpperCase(Locale.US),
                 Leniency.POSSIBLE, Long.MAX_VALUE);
         for (PhoneNumberMatch match : matches) {
             LinkSpec spec = new LinkSpec();
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index c11089b..49f77e1 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -194,7 +194,7 @@
     private static Set<String> getSimCountries(Context context) {
         Set<String> result = new HashSet<>();
 
-        TelephonyManager tm = TelephonyManager.from(context);
+        TelephonyManager tm = context.getSystemService(TelephonyManager.class);
 
         if (tm != null) {
             String iso = tm.getSimCountryIso().toUpperCase(Locale.US);
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index 5857642..045a680 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -133,7 +133,7 @@
     boolean isChangeEnabledByUid(long changeId, int uid);
 
     /**
-     * Add overrides to compatibility changes.
+     * Add overrides to compatibility changes. Kills the app to allow the changes to take effect.
      *
      * @param overrides Parcelable containing the compat change overrides to be applied.
      * @param packageName The package name of the app whose changes will be overridden.
@@ -142,7 +142,28 @@
     void setOverrides(in CompatibilityChangeConfig overrides, in String packageName);
 
     /**
-     * Revert overrides to compatibility changes.
+     * Add overrides to compatibility changes. Doesn't kill the app, to be only used in tests.
+     *
+     * @param overrides Parcelable containing the compat change overrides to be applied.
+     * @param packageName The package name of the app whose changes will be overridden.
+     *
+     */
+    void setOverridesForTest(in CompatibilityChangeConfig overrides, in String packageName);
+
+    /**
+     * Removes an override previously added via {@link #setOverrides(CompatibilityChangeConfig,
+     * String)}. This restores the default behaviour for the given change and app, once any app
+     * processes have been restarted.
+     * Kills the app to allow the changes to take effect.
+     *
+     * @param changeId    The ID of the change that was overridden.
+     * @param packageName The app package name that was overridden.
+     * @return {@code true} if an override existed;
+     */
+    boolean clearOverride(long changeId, String packageName);
+
+    /**
+     * Revert overrides to compatibility changes. Kills the app to allow the changes to take effect.
      *
      * @param packageName The package name of the app whose overrides will be cleared.
      *
diff --git a/core/java/com/android/internal/package-info.java b/core/java/com/android/internal/package-info.java
new file mode 100644
index 0000000..8a226db
--- /dev/null
+++ b/core/java/com/android/internal/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * @hide
+ */
+package com.android.internal;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9f77407..545538b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -142,7 +142,7 @@
     <protected-broadcast android:name="android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.device.action.UUID" />
     <protected-broadcast android:name="android.bluetooth.device.action.MAS_INSTANCE" />
-    <protected-broadcast android:name="android.bluetooth.device.action.ALIAS_CHANGED" />
+    <protected-broadcast android:name="android.bluetooth.action.ALIAS_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.device.action.FOUND" />
     <protected-broadcast android:name="android.bluetooth.device.action.CLASS_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.device.action.ACL_CONNECTED" />
diff --git a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
index 823fca5..85aa118 100644
--- a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
+++ b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
@@ -23,13 +23,23 @@
 
 import android.os.Parcel;
 import android.util.Pair;
+import android.util.Xml;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.util.FastXmlSerializer;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 
 @SmallTest
@@ -104,11 +114,15 @@
         });
     }
 
-
     @Test
     public void testParceledConfigIsEquivalent() {
         BrightnessConfiguration.Builder builder =
                 new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+        builder.setShouldCollectColorSamples(true);
+        builder.addCorrectionByCategory(3,
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+        builder.addCorrectionByPackageName("a.package.name",
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
         BrightnessConfiguration config = builder.build();
         Parcel p = Parcel.obtain();
         p.writeParcelable(config, 0 /*flags*/);
@@ -119,12 +133,49 @@
     }
 
     @Test
+    public void testWriteReadXml() throws IOException, XmlPullParserException {
+        BrightnessConfiguration.Builder builder =
+                new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+        builder.setShouldCollectColorSamples(true);
+        builder.addCorrectionByCategory(3,
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+        builder.addCorrectionByPackageName("a.package.name",
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+        BrightnessConfiguration config = builder.build();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        XmlSerializer out = new FastXmlSerializer();
+        out.setOutput(baos, StandardCharsets.UTF_8.name());
+        out.startDocument(null, true);
+        config.saveToXml(out);
+        out.endDocument();
+        baos.flush();
+
+        ByteArrayInputStream input = new ByteArrayInputStream(baos.toByteArray());
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(input, StandardCharsets.UTF_8.name());
+        BrightnessConfiguration loadedConfig = BrightnessConfiguration.loadFromXml(parser);
+
+        assertEquals(config, loadedConfig);
+    }
+
+    @Test
     public void testEquals() {
         BrightnessConfiguration.Builder builder =
                 new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+        builder.setShouldCollectColorSamples(true);
+        builder.addCorrectionByCategory(3,
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+        builder.addCorrectionByPackageName("a.package.name",
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
         BrightnessConfiguration baseConfig = builder.build();
 
         builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+        builder.setShouldCollectColorSamples(true);
+        builder.addCorrectionByCategory(3,
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+        builder.addCorrectionByPackageName("a.package.name",
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
         BrightnessConfiguration identicalConfig = builder.build();
         assertEquals(baseConfig, identicalConfig);
         assertEquals("hashCodes must be equal for identical configs",
@@ -133,14 +184,37 @@
         float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length);
         lux[lux.length - 1] = lux[lux.length - 1] * 2;
         builder = new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
+        builder.setShouldCollectColorSamples(true);
+        builder.addCorrectionByCategory(3,
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+        builder.addCorrectionByPackageName("a.package.name",
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
         BrightnessConfiguration luxDifferConfig = builder.build();
         assertNotEquals(baseConfig, luxDifferConfig);
 
         float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length);
         nits[nits.length - 1] = nits[nits.length - 1] * 2;
         builder = new BrightnessConfiguration.Builder(LUX_LEVELS, nits);
+        builder.setShouldCollectColorSamples(true);
+        builder.addCorrectionByCategory(3,
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+        builder.addCorrectionByPackageName("a.package.name",
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
         BrightnessConfiguration nitsDifferConfig = builder.build();
         assertNotEquals(baseConfig, nitsDifferConfig);
+
+        builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+        builder.addCorrectionByCategory(3,
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+        builder.addCorrectionByPackageName("a.package.name",
+                BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+        BrightnessConfiguration colorCollectionDiffers = builder.build();
+        assertNotEquals(baseConfig, colorCollectionDiffers);
+
+        builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+        builder.setShouldCollectColorSamples(true);
+        BrightnessConfiguration correctionsDiffer = builder.build();
+        assertNotEquals(baseConfig, correctionsDiffer);
     }
 
     private static void assertArrayEquals(float[] expected, float[] actual, String name) {
diff --git a/media/java/android/media/tv/OWNER b/media/java/android/media/tv/OWNER
deleted file mode 100644
index 64c0bb5..0000000
--- a/media/java/android/media/tv/OWNER
+++ /dev/null
@@ -1,5 +0,0 @@
-amyjojo@google.com
-nchalko@google.com
-shubang@google.com
-quxiangfang@google.com
-
diff --git a/media/java/android/media/tv/OWNERS b/media/java/android/media/tv/OWNERS
index 4a03b3c..64c0bb5 100644
--- a/media/java/android/media/tv/OWNERS
+++ b/media/java/android/media/tv/OWNERS
@@ -1,2 +1,5 @@
+amyjojo@google.com
 nchalko@google.com
+shubang@google.com
+quxiangfang@google.com
 
diff --git a/packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml b/packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml
deleted file mode 100644
index 918abd9..0000000
--- a/packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2019 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<com.android.systemui.statusbar.car.privacy.OngoingPrivacyChip
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/car_privacy_chip"
-    android:layout_width="wrap_content"
-    android:layout_height="match_parent"
-    android:layout_margin="@dimen/ongoing_appops_chip_margin"
-    android:layout_toStartOf="@+id/clock_container"
-    android:focusable="true"
-    android:gravity="center_vertical|end"
-    android:orientation="horizontal"
-    android:paddingEnd="@dimen/ongoing_appops_chip_side_padding"
-    android:paddingStart="@dimen/ongoing_appops_chip_side_padding"
-    android:visibility="visible">
-
-    <LinearLayout
-        android:id="@+id/icons_container"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:gravity="center_vertical|start"/>
-</com.android.systemui.statusbar.car.privacy.OngoingPrivacyChip>
\ No newline at end of file
diff --git a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
index 7299ddf..ce0d31c 100644
--- a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
@@ -65,8 +65,6 @@
             />
         </FrameLayout>
 
-        <include layout="@layout/car_ongoing_privacy_chip"/>
-
         <FrameLayout
             android:id="@+id/clock_container"
             android:layout_width="wrap_content"
diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml
index e2da91b..ee79653 100644
--- a/packages/CarSystemUI/res/values/dimens.xml
+++ b/packages/CarSystemUI/res/values/dimens.xml
@@ -59,18 +59,6 @@
     <dimen name="car_keyline_1">24dp</dimen>
     <dimen name="car_keyline_2">96dp</dimen>
     <dimen name="car_keyline_3">128dp</dimen>
-    <dimen name="privacy_chip_icon_height">36dp</dimen>
-    <dimen name="privacy_chip_icon_padding_left">0dp</dimen>
-    <dimen name="privacy_chip_icon_padding_right">0dp</dimen>
-    <dimen name="privacy_chip_icon_padding_top">0dp</dimen>
-    <dimen name="privacy_chip_icon_padding_bottom">0dp</dimen>
-
-    <dimen name="privacy_chip_text_padding_left">0dp</dimen>
-    <dimen name="privacy_chip_text_padding_right">0dp</dimen>
-    <dimen name="privacy_chip_text_padding_top">0dp</dimen>
-    <dimen name="privacy_chip_text_padding_bottom">0dp</dimen>
-
-    <dimen name="privacy_chip_icon_max_height">100dp</dimen>
 
     <!-- Height of icons in Ongoing App Ops dialog. Both App Op icon and application icon -->
     <dimen name="ongoing_appops_dialog_icon_height">48dp</dimen>
@@ -86,16 +74,6 @@
     <dimen name="ongoing_appops_chip_bg_padding">4dp</dimen>
     <!-- Radius of Ongoing App Ops chip corners -->
     <dimen name="ongoing_appops_chip_bg_corner_radius">12dp</dimen>
-    <!-- Start padding for the app icon displayed in the dialog -->
-    <dimen name="privacy_dialog_app_icon_padding_start">40dp</dimen>
-    <!-- End padding for the app opps icon displayed in the dialog -->
-    <dimen name="privacy_dialog_app_ops_icon_padding_end">40dp</dimen>
-    <!-- Top padding for the list of application displayed in the dialog -->
-    <dimen name="privacy_dialog_app_list_padding_top">20dp</dimen>
-    <!-- Top padding for the dialog container-->
-    <dimen name="privacy_dialog_container_padding_top">10dp</dimen>
-    <!-- Top padding for the dialog title-->
-    <dimen name="privacy_dialog_title_padding_start">10dp</dimen>
 
     <!-- Car volume dimens. -->
     <dimen name="car_volume_item_icon_size">@dimen/car_primary_icon_size</dimen>
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java
deleted file mode 100644
index 88d641e..0000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import android.app.ActivityManager;
-import android.app.AppOpsManager;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.appops.AppOpItem;
-import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.plugins.ActivityStarter;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-/**
- * Layout defining the privacy chip that will be displayed in CarStatusRar with the information for
- * which applications are using AppOpps permission fpr camera, mic and location.
- */
-public class OngoingPrivacyChip extends LinearLayout implements View.OnClickListener {
-
-    private Context mContext;
-    private Handler mHandler;
-
-    private LinearLayout mIconsContainer;
-    private List<PrivacyItem> mPrivacyItems;
-    private static AppOpsController sAppOpsController;
-    private UserManager mUserManager;
-    private int mCurrentUser;
-    private List<Integer> mCurrentUserIds;
-    private boolean mListening = false;
-    PrivacyDialogBuilder mPrivacyDialogBuilder;
-    private LinearLayout mPrivacyChip;
-    private ActivityStarter mActivityStarter;
-
-    protected static final int[] OPS = new int[]{
-            AppOpsManager.OP_CAMERA,
-            AppOpsManager.OP_RECORD_AUDIO,
-            AppOpsManager.OP_COARSE_LOCATION,
-            AppOpsManager.OP_FINE_LOCATION
-    };
-
-    public OngoingPrivacyChip(Context context) {
-        super(context, null);
-        init(context);
-    }
-
-    public OngoingPrivacyChip(Context context, AttributeSet attr) {
-        super(context, attr);
-        init(context);
-    }
-
-    public OngoingPrivacyChip(Context context, AttributeSet attr, int defStyle) {
-        super(context, attr, defStyle);
-        init(context);
-    }
-
-    public OngoingPrivacyChip(Context context, AttributeSet attr, int defStyle, int a) {
-        super(context, attr, defStyle, a);
-        init(context);
-    }
-
-    private void init(Context context) {
-        mContext = context;
-        mHandler = new Handler(Looper.getMainLooper());
-        mPrivacyItems = new ArrayList<>();
-        sAppOpsController = Dependency.get(AppOpsController.class);
-        mUserManager = mContext.getSystemService(UserManager.class);
-        mActivityStarter = Dependency.get(ActivityStarter.class);
-        mCurrentUser = ActivityManager.getCurrentUser();
-        mCurrentUserIds = mUserManager.getProfiles(mCurrentUser).stream().map(
-                userInfo -> userInfo.id).collect(Collectors.toList());
-
-        mPrivacyDialogBuilder = new PrivacyDialogBuilder(context, mPrivacyItems);
-    }
-
-    private AppOpsController.Callback mCallback = new AppOpsController.Callback() {
-
-        @Override
-        public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
-            int userId = UserHandle.getUserId(uid);
-            if (mCurrentUserIds.contains(userId)) {
-                updatePrivacyList();
-            }
-        }
-    };
-
-    @Override
-    public void onFinishInflate() {
-        mIconsContainer = findViewById(R.id.icons_container);
-        mPrivacyChip = (LinearLayout) findViewById(R.id.car_privacy_chip);
-        if (mPrivacyChip != null) {
-            mPrivacyChip.setOnClickListener(this);
-            setListening(true);
-        }
-    }
-
-    @Override
-    public void onDetachedFromWindow() {
-        if (mPrivacyChip != null) {
-            setListening(false);
-        }
-        super.onDetachedFromWindow();
-    }
-
-    @Override
-    public void onClick(View v) {
-        updatePrivacyList();
-        mHandler.post(() -> {
-            mActivityStarter.postStartActivityDismissingKeyguard(
-                    new Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE), 0);
-        });
-    }
-
-    private void setListening(boolean listen) {
-        if (mListening == listen) {
-            return;
-        }
-        mListening = listen;
-        if (mListening) {
-            sAppOpsController.addCallback(OPS, mCallback);
-            updatePrivacyList();
-        } else {
-            sAppOpsController.removeCallback(OPS, mCallback);
-        }
-    }
-
-    private void updatePrivacyList() {
-        List<PrivacyItem> privacyItems = mCurrentUserIds.stream()
-                .flatMap(item -> sAppOpsController.getActiveAppOpsForUser(item).stream())
-                .filter(Objects::nonNull)
-                .map(item -> toPrivacyItem(item))
-                .filter(Objects::nonNull)
-                .collect(Collectors.toList());
-        if (!privacyItems.equals(mPrivacyItems)) {
-            mPrivacyItems = privacyItems;
-            mPrivacyDialogBuilder = new PrivacyDialogBuilder(mContext, mPrivacyItems);
-            mHandler.post(this::updateView);
-        }
-    }
-
-    private PrivacyItem toPrivacyItem(AppOpItem appOpItem) {
-        PrivacyType type;
-        switch (appOpItem.getCode()) {
-            case AppOpsManager.OP_CAMERA:
-                type = PrivacyType.TYPE_CAMERA;
-                break;
-            case AppOpsManager.OP_COARSE_LOCATION:
-                type = PrivacyType.TYPE_LOCATION;
-                break;
-            case AppOpsManager.OP_FINE_LOCATION:
-                type = PrivacyType.TYPE_LOCATION;
-                break;
-            case AppOpsManager.OP_RECORD_AUDIO:
-                type = PrivacyType.TYPE_MICROPHONE;
-                break;
-            default:
-                return null;
-        }
-        PrivacyApplication app = new PrivacyApplication(appOpItem.getPackageName(), mContext);
-        return new PrivacyItem(type, app, appOpItem.getTimeStarted());
-    }
-
-    // Should only be called if the mPrivacyDialogBuilder icons or app changed
-    private void updateView() {
-        if (mPrivacyItems.isEmpty()) {
-            mPrivacyChip.setVisibility(GONE);
-            return;
-        }
-        mPrivacyChip.setVisibility(VISIBLE);
-        setIcons(mPrivacyDialogBuilder);
-
-        requestLayout();
-    }
-
-    private void setIcons(PrivacyDialogBuilder dialogBuilder) {
-        mIconsContainer.removeAllViews();
-        dialogBuilder.generateIcons().forEach(item -> {
-            int size = mContext.getResources().getDimensionPixelSize(
-                    R.dimen.privacy_chip_icon_height);
-            ImageView image = new ImageView(mContext);
-            image.setImageDrawable(item);
-            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(size, size);
-
-            int leftPadding = mContext.getResources().getDimensionPixelSize(
-                    R.dimen.privacy_chip_icon_padding_left);
-            int topPadding = mContext.getResources().getDimensionPixelSize(
-                    R.dimen.privacy_chip_icon_padding_top);
-            int rightPadding = mContext.getResources().getDimensionPixelSize(
-                    R.dimen.privacy_chip_icon_padding_right);
-            int bottomPadding = mContext.getResources().getDimensionPixelSize(
-                    R.dimen.privacy_chip_icon_padding_bottom);
-            image.setLayoutParams(layoutParams);
-            image.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
-            mIconsContainer.addView(image);
-        });
-    }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
deleted file mode 100644
index a5d3bf7..0000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-
-import java.util.Objects;
-
-/**
- * Class to hold the data for the applications that are using the AppOps permissions.
- */
-public class PrivacyApplication {
-    private static final String TAG = "PrivacyApplication";
-
-    private String mPackageName;
-    private Drawable mIcon;
-    private String mApplicationName;
-
-    public PrivacyApplication(String packageName, Context context) {
-        mPackageName = packageName;
-        try {
-            ApplicationInfo app = context.getPackageManager()
-                    .getApplicationInfoAsUser(packageName, 0,
-                            ActivityManager.getCurrentUser());
-            mIcon = context.getPackageManager().getApplicationIcon(app);
-            mApplicationName = context.getPackageManager().getApplicationLabel(app).toString();
-        } catch (PackageManager.NameNotFoundException e) {
-            mApplicationName = packageName;
-            Log.e(TAG, "Failed to to find package name", e);
-        }
-    }
-
-    /**
-     * Gets the application name.
-     */
-    public Drawable getIcon() {
-        return mIcon;
-    }
-
-    /**
-     * Gets the application name.
-     */
-    public String getApplicationName() {
-        return mApplicationName;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        PrivacyApplication that = (PrivacyApplication) o;
-        return mPackageName.equals(that.mPackageName);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mPackageName);
-    }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java
deleted file mode 100644
index 3b83e7c..0000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-/**
- * Helper class to build the {@link OngoingPrivacyDialog}
- */
-public class PrivacyDialogBuilder {
-
-    private Map<PrivacyType, List<PrivacyItem>> mItemsByType;
-    private PrivacyApplication mApplication;
-    private Context mContext;
-
-    public PrivacyDialogBuilder(Context context, List<PrivacyItem> itemsList) {
-        mContext = context;
-        mItemsByType = itemsList.stream().filter(Objects::nonNull).collect(
-                Collectors.groupingBy(PrivacyItem::getPrivacyType));
-        List<PrivacyApplication> apps = itemsList.stream().filter(Objects::nonNull).map(
-                PrivacyItem::getPrivacyApplication).distinct().collect(Collectors.toList());
-        mApplication = apps.size() == 1 ? apps.get(0) : null;
-    }
-
-    /**
-     * Gets the icon id for all the {@link PrivacyItem} in the same order as of itemList.
-     */
-    public List<Drawable> generateIcons() {
-        return mItemsByType.keySet().stream().map(item -> item.getIconId(mContext)).collect(
-                Collectors.toList());
-    }
-
-    /**
-     * Gets the application object.
-     */
-    public PrivacyApplication getApplication() {
-        return mApplication;
-    }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java
deleted file mode 100644
index d3e123e..0000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import java.util.Objects;
-
-/**
- * Class for holding the data of each privacy item displayed in {@link OngoingPrivacyDialog}
- */
-public class PrivacyItem {
-
-    private PrivacyType mPrivacyType;
-    private PrivacyApplication mPrivacyApplication;
-
-    public PrivacyItem(PrivacyType privacyType, PrivacyApplication privacyApplication,
-            long timeStarted) {
-        this.mPrivacyType = privacyType;
-        this.mPrivacyApplication = privacyApplication;
-    }
-
-    /**
-     * Gets the application object.
-     */
-    public PrivacyApplication getPrivacyApplication() {
-        return mPrivacyApplication;
-    }
-
-    /**
-     * Gets the privacy type for the application.
-     */
-    public PrivacyType getPrivacyType() {
-        return mPrivacyType;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        PrivacyItem that = (PrivacyItem) o;
-        return mPrivacyType == that.mPrivacyType
-                && mPrivacyApplication.equals(that.mPrivacyApplication);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mPrivacyType, mPrivacyApplication);
-    }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java
deleted file mode 100644
index 8955c87..0000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-
-import com.android.systemui.R;
-
-/**
- * Enum for storing data for camera, mic and location.
- */
-public enum PrivacyType {
-    TYPE_CAMERA(R.string.privacy_type_camera, com.android.internal.R.drawable.ic_camera),
-    TYPE_LOCATION(R.string.privacy_type_location, R.drawable.stat_sys_location),
-    TYPE_MICROPHONE(R.string.privacy_type_microphone, R.drawable.ic_mic_white);
-
-    private int mNameId;
-    private int mIconId;
-
-    PrivacyType(int nameId, int iconId) {
-        mNameId = nameId;
-        mIconId = iconId;
-    }
-
-    /**
-     * Get the icon Id.
-     */
-    public Drawable getIconId(Context context) {
-        return context.getResources().getDrawable(mIconId, null);
-    }
-
-    /**
-     * Get the name Id.
-     */
-    public String getNameId(Context context) {
-        return context.getResources().getString(mNameId);
-    }
-}
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 97b2cb5..3ff5cf4 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Middelmatig"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Vinnig"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Baie vinnig"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Verval"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Ontkoppel"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ontkoppel tans…"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 62d5dca..264d8de 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"መካከለኛ"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"ፈጣን"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"እጅግ በጣም ፈጣን"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ጊዜው አልፏል"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"ተለያይቷል"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"በመለያየት ላይ..."</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index c786e09..c230236 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"متوسطة"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"سريعة"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"سريعة جدًا"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"منتهية الصلاحية"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"غير متصل"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"جارٍ قطع الاتصال..."</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 552fbb8..ab0ed29 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"মধ্যমীয়া"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"দ্ৰুত"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"অতি দ্ৰুত"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ম্যাদ উকলিছে"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"সংযোগ বিচ্ছিন্ন কৰা হ’ল"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"সংযোগ বিচ্ছিন্ন কৰি থকা হৈছে…"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 3af2e25..fe62d31 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Orta"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Sürətli"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Çox Sürətli"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Vaxtı keçib"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Ayrıldı"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ayrılır..."</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 8a76242..1619584 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Srednja"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Brza"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Veoma brza"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Isteklo"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Veza je prekinuta"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Prekidanje veze..."</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 5ed4495..0f2df49 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Сярэдняя"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Хуткая"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Вельмі хуткая"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Тэрмін скончыўся"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Адключана"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Адключэнне..."</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index f7a7153..a3be2812 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Средна"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Бърза"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Много бърза"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Изтекло"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Изкл."</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Изключва се..."</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index f4c677f..743de50 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"মাঝারি"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"দ্রুত"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"খুব দ্রুত"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"মেয়াদ শেষ হয়ে গেছে"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"ডিসকানেক্ট করা হয়েছে"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"ডিসকানেক্ট হচ্ছে..."</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index fc653b7..75a4047 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Srednja brzina"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Brzo"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Veoma brzo"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Istekao"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Isključen"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Prekidanje veze…"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index f79375e..8627cf3 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Mitjana"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Ràpida"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Molt ràpida"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Caducat"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconnectat"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"S\'està desconnectant..."</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 64400a4..6fef07a 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Střední"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rychlá"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Velmi rychlá"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Platnost vypršela"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Odpojeno"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Odpojování..."</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index de7a228..80ee95e 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Middel"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Hurtig"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Meget hurtig"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Udløbet"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> – <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Afbrudt"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Afbryder ..."</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index eafe9d0..7dee120 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Μέτρια"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Γρήγορη"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Πολύ γρήγορη"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Έληξε"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Αποσυνδέθηκε"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Αποσύνδεση..."</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 840f5ee..41c817e 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Media"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Muy rápida"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Vencido"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index c86eb34..897eaa3 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Media"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Muy rápida"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Caducado"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index f59b96a..9b94222 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Keskmine"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Kiire"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Väga kiire"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Aegunud"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Ühendus katkestatud"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ühenduse katkestamine ..."</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 9648139..b0e4b26 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Tartekoa"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Bizkorra"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Oso bizkorra"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Iraungita"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Deskonektatuta"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Deskonektatzen…"</string>
@@ -455,7 +454,7 @@
     <string name="cancel" msgid="5665114069455378395">"Utzi"</string>
     <string name="okay" msgid="949938843324579502">"Ados"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktibatu"</string>
-    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktibatu \"Ez molestatu\" modua"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktibatu ez molestatzeko modua"</string>
     <string name="zen_mode_settings_summary_off" msgid="3832876036123504076">"Inoiz ez"</string>
     <string name="zen_interruption_level_priority" msgid="5392140786447823299">"Lehentasuna dutenak soilik"</string>
     <string name="zen_mode_and_condition" msgid="8877086090066332516">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 3e8de97..7298826 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"متوسط"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"سریع"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"خیلی سریع"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"منقضی‌شده"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"اتصال قطع شد"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"در حال قطع اتصال..."</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 68ddf7d..6f58f03 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Kohtuullinen"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Nopea"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Hyvin nopea"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Vanhentunut"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Yhteys katkaistu"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Katkaistaan yhteyttä..."</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index ef4800c..a5526f3 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Moyenne"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Élevée"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Très rapide"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expiré"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> : <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Déconnecté"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Déconnexion…"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 256ea03a..eaab027 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Media"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Moi rápida"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Caducou"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando..."</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index ed50f4b..00fd024 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"મધ્યમ"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"ઝડપી"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"ખૂબ ઝડપી"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"સમય સમાપ્ત થયો"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"ડિસ્કનેક્ટ કર્યું"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"ડિસ્કનેક્ટ થઈ રહ્યું છે..."</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 550eaf8..96aec94 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"मध्यम"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"तेज़"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"अत्‍यधिक तेज़"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"समयसीमा खत्म हो गई"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"डिसकनेक्ट किया गया"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"डिस्‍कनेक्‍ट हो रहा है..."</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 18ea1de..6df46ca 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Srednje"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Brzo"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Vrlo brzo"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Isteklo"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Niste povezani"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Isključivanje…"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 7baa044..6b5b05e 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Közepes"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Gyors"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Nagyon gyors"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Lejárt"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Szétkapcsolva"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Szétkapcsolás..."</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index a5b03ea..c4002b9 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Միջին"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Արագ"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Շատ արագ"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Սպառվել է"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Անջատված է"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Անջատվում է..."</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index dea51a8..753f225 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Sedang"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Cepat"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Sangat Cepat"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Sudah tidak berlaku"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Sambungan terputus"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Memutus sambungan..."</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 0a85d06..b1d40bf 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Miðlungshratt"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Hratt"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Mjög hratt"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Útrunninn"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Aftengt"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Aftengist…"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 980bdf9..7f2bd3e 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Media"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Veloce"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Molto veloce"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Scaduto"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Disconnesso"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Disconnessione..."</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 77fd156..bdd1bab 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"בינונית"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"מהירה"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"מהירה מאוד"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"התוקף פג"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"מנותק"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"מתנתק..."</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 1d6b3d5..a6192a4 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"普通"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"速い"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"非常に速い"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"期限切れ"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"切断"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"切断中..."</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index a69713a..a3633f6 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"საშუალო"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"სწრაფი"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"ძალიან სწრაფი"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ვადაგასულია"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"კავშირი გაწყვეტილია"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"მიმდინარეობს გათიშვა…"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 380d648..0962e55 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Орташа"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Жылдам"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Өте жылдам"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Мерзімі өтті."</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Ажыратылған"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ажыратылуда…"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 478e036..45620e8 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"មធ្យម"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"លឿន"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"លឿន​ណាស់"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ផុតកំណត់"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"បាន​ផ្ដាច់"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"កំពុង​ផ្ដាច់…"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 73aa998..1fc2e4a 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"ಮಧ್ಯಮ"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"ವೇಗ"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"ತುಂಬಾ ವೇಗವಾಗಿದೆ"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ಅವಧಿ ಮುಕ್ತಾಯವಾಗಿದೆ"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗುತ್ತಿದೆ..."</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 3ecde32..8e7c697 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"보통"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"빠름"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"매우 빠름"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"만료됨"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"연결 끊김"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"연결을 끊는 중…"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index ca8992f..18a1468 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Орто"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Ылдам"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Абдан ылдам"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Мөөнөтү бүткөн"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Ажыратылган"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ажыратылууда…"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index b8a9322..808d5a7 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"ປານກາງ"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"ໄວ"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"ໄວຫຼາຍ"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ໝົດອາຍຸແລ້ວ"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"ຕັດການເຊື່ອມຕໍ່ແລ້ວ"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"ກຳລັງຢຸດການເຊື່ອມຕໍ່..."</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 3d6dfbb..78d1b1b 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Vidutinis"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Greitas"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Labai greitas"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Baigėsi galiojimo laikas"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Atsijungęs (-usi)"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Atjungiama..."</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index bf0c97d..0ae10aa 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Vidējs"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Ātrs"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Ļoti ātrs"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Beidzies derīguma termiņš"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Atvienots"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Notiek atvienošana..."</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 53b0d4c..9850ac5 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Средна"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Брза"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Многу брза"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Истечено"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Исклучено"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Се исклучува..."</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 66ff005..2692a30 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"ഇടത്തരം"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"വേഗത്തിൽ"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"വളരെ വേഗത്തിൽ"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"കാലഹരണപ്പെട്ടത്"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"വിച്ഛേദിച്ചു"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"വിച്‌ഛേദിക്കുന്നു..."</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 75633ab..966cdff 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"मध्‍यम"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"जलद"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"खूप जलद"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"मुदत संपली"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"डिस्कनेक्ट केले"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"डिस्कनेक्ट करत आहे..."</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index fad37fe..88d7c7d 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Sederhana"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Laju"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Sangat Laju"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Tamat tempoh"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Diputuskan sambungan"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Memutuskan sambungan..."</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index fd626f6c..6dfd290 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"အတော်အသင့်"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"မြန်"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"အလွန်မြန်"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"သက်တမ်းကုန်သွားပါပြီ"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"ချိတ်ဆက်မှုပြတ်တောက်သည်"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"အဆက်အသွယ်ဖြတ်တောက်သည်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index baf3c64..760c409 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Middels"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rask"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Veldig rask"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Utløpt"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Frakoblet"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Kobler fra…"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 00a3022..77f87ff 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"मध्यम"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"छिटो"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"धेरै छिटो"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"म्याद सकियो"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"विच्छेदन गरियो"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"जडान हटाइँदै ..."</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 533b0f2..55f56d9 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Gemiddeld"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Snel"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Zeer snel"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Verlopen"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Verbinding verbroken"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Verbinding verbreken..."</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 4a2ab80..98c302d 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"ମଧ୍ୟମ"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"ଦ୍ରୁତ"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"ଅତି ଦ୍ରୁତ"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ମିଆଦ ଶେଷ ହୋଇଯାଇଛି"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"ବିଛିନ୍ନ ହେଲା"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"ବିଚ୍ଛିନ୍ନ କରୁଛି…"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 62da49b..525ad2e 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"ਔਸਤ"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"ਤੇਜ਼"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"ਬਹੁਤ ਤੇਜ਼"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ਮਿਆਦ ਮੁੱਕ ਗਈ"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"ਡਿਸਕਨੈਕਟ ਕੀਤਾ"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"ਡਿਸਕਨੈਕਟ ਕਰ ਰਿਹਾ ਹੈ..."</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 027afc3..69ebc59 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Średnia"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Szybka"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Bardzo szybka"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Ważność wygasła"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Rozłączona"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Rozłączanie..."</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 9259c03..62017f1 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Média"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Muito rápida"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expirado"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 0961b27..8304768 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Média"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Muito rápida"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expirado"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Desligado"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"A desligar..."</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 9259c03..62017f1 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Média"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Muito rápida"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expirado"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 1fc1d35..50ea4a0 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Medie"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rapidă"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Foarte rapidă"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expirat"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Deconectat"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"În curs de deconectare..."</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index c3baea2..0582a0c 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Средняя"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Быстрая"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Очень быстрая"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Срок действия истек"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Нет подключения"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Отключение..."</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index f8d2d08..43a4978 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"මධ්‍යම"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"වේගවත්"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"ඉතා වේගවත්"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"කල් ඉකුත් විය"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"විසන්ධි වුණි"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"විසන්ධි වෙමින්…"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 0d576b4..3a3958f 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Stredná"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Vysoká"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Veľmi vysoká"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Platnosť vypršala"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Odpojený"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Prebieha odpájanie..."</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 7c62d52..068f221 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Srednje hitra"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Hitra"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Zelo hitra"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Poteklo"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Prekinjena povezava"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Prekinjanje povezave ..."</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 7a1bdb5..54d4637 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Mesatare"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"E shpejtë"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Shumë e shpejtë"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Skaduar"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Shkëputur"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Po shkëputet..."</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index e809ab9..ab081ae 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Средња"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Брза"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Веома брза"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Истекло"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Веза је прекинута"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Прекидање везе..."</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 52a82db..cab971f 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Medelsnabb"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Snabb"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Mycket snabb"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Har upphört att gälla"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Kopplas ifrån"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Kopplar ifrån…"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index c83388a..df71b82 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Wastani"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Haraka"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Haraka Sana"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Muda umeisha"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Haijaunganishwa"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Inatenganisha..."</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 856fd4f..084ec16 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"நடுத்தரம்"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"வேகம்"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"மிகவும் வேகமானது"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"காலாவதியாகிவிட்டது"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"தொடர்பு துண்டிக்கப்பட்டது"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"துண்டிக்கிறது..."</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index cc17247..cbcaf1a 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"మధ్యస్థం"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"వేగవంతం"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"చాలా వేగవంతం"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"గడువు ముగిసింది"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"డిస్‌కనెక్ట్ చేయబడింది"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"డిస్‌కనెక్ట్ చేస్తోంది..."</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 4feb0d6..fa8caa1 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"ปานกลาง"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"เร็ว"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"เร็วมาก"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"หมดอายุแล้ว"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"ตัดการเชื่อมต่อ"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"กำลังตัดการเชื่อมต่อ..."</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index e6963b9..21fe58c 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Katamtaman"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Mabilis"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Napakabilis"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Nag-expire na"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Hindi nakakonekta"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Nadidiskonekta..."</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index bd457d3..4e7f38d 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Orta"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Hızlı"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Çok Hızlı"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Süresi sona erdi"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Bağlantı kesildi"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Bağlantı kesiliyor…"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 36a82ea..9807417 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Середня"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Швидка"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Дуже швидка"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Термін дії минув"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>: <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Роз’єднано"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Відключення..."</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 50dc72e..e17b0b0 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"متوسط"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"تیز"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"بہت تیز"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"میعاد ختم ہو گئی"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"منقطع"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"منقطع کیا جارہا ہے…"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 38edb6d0..ea51eba 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"O‘rtacha"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Tez"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Juda tez"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Muddati tugagan"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Uzildi"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Uzilyapti…"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index e0798aa..0b71a8c 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Trung bình"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Nhanh"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Rất nhanh"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Đã hết hạn"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Đã ngắt kết nối"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Đang ngắt kết nối…"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 4303615..1805694 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"适中"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"快"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"很快"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"已失效"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"已断开连接"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"正在断开连接..."</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index f3b8653..1d217b5 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"適中"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"快"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"非常快"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"已過期"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"已中斷連線"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"正在中斷連線..."</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 53b54c4..ee68665 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"適中"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"快"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"非常快"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"已失效"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"已中斷連線"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"正在中斷連線…"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 249e73c..820aa77 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -61,8 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Okumaphakathi"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Sheshayo"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Kushesha kakhulu"</string>
-    <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
-    <skip />
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Iphelelwe isikhathi"</string>
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Ayixhunyiwe"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Inqamula uxhumano kwi-inthanethi..."</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index a1ef831..80240af 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -609,6 +609,9 @@
     <string name="bluetooth_select_a2dp_codec_sample_rate">Bluetooth Audio Sample Rate</string>
     <!-- UI debug setting: Trigger Bluetooth Audio Codec Selection: Sample Rate -->
     <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title">Trigger Bluetooth Audio Codec\u000ASelection: Sample Rate</string>
+    <!-- UI debug setting: Label for unsupported Bluetooth Audio Codec. [CHAR LIMIT=none] -->
+    <string name="bluetooth_select_a2dp_codec_type_help_info">Gray-out means not supported by phone
+        or headset</string>
 
     <!-- UI debug setting: Trigger Bluetooth Audio Bits Per Sample Selection -->
     <string name="bluetooth_select_a2dp_codec_bits_per_sample">Bluetooth Audio Bits Per Sample</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 2507a34..0095692 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -442,12 +442,12 @@
 
     /**
      * Get name from remote device
-     * @return {@link BluetoothDevice#getAliasName()} if
-     * {@link BluetoothDevice#getAliasName()} is not null otherwise return
+     * @return {@link BluetoothDevice#getAlias()} if
+     * {@link BluetoothDevice#getAlias()} is not null otherwise return
      * {@link BluetoothDevice#getAddress()}
      */
     public String getName() {
-        final String aliasName = mDevice.getAliasName();
+        final String aliasName = mDevice.getAlias();
         return TextUtils.isEmpty(aliasName) ? getAddress() : aliasName;
     }
 
@@ -505,7 +505,7 @@
      * @return true if device's alias name is not null nor empty, false otherwise
      */
     public boolean hasHumanReadableName() {
-        return !TextUtils.isEmpty(mDevice.getAliasName());
+        return !TextUtils.isEmpty(mDevice.getAlias());
     }
 
     /**
@@ -652,7 +652,7 @@
         }
 
         if (BluetoothUtils.D) {
-            Log.e(TAG, "updating profiles for " + mDevice.getAliasName() + ", " + mDevice);
+            Log.e(TAG, "updating profiles for " + mDevice.getAlias() + ", " + mDevice);
             BluetoothClass bluetoothClass = mDevice.getBluetoothClass();
 
             if (bluetoothClass != null) Log.v(TAG, "Class: " + bluetoothClass.toString());
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index 9f71033..cca9cfa 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -168,7 +168,7 @@
             return cachedDevice.getName();
         }
 
-        String name = device.getAliasName();
+        String name = device.getAlias();
         if (name != null) {
             return name;
         }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index aef7fae..2c4f57f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -92,9 +92,9 @@
         when(mDevice1.getName()).thenReturn(DEVICE_NAME_1);
         when(mDevice2.getName()).thenReturn(DEVICE_NAME_2);
         when(mDevice3.getName()).thenReturn(DEVICE_NAME_3);
-        when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1);
-        when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2);
-        when(mDevice3.getAliasName()).thenReturn(DEVICE_ALIAS_3);
+        when(mDevice1.getAlias()).thenReturn(DEVICE_ALIAS_1);
+        when(mDevice2.getAlias()).thenReturn(DEVICE_ALIAS_2);
+        when(mDevice3.getAlias()).thenReturn(DEVICE_ALIAS_3);
         when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS_1);
         when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS_2);
         when(mDevice3.getBluetoothClass()).thenReturn(DEVICE_CLASS_2);
@@ -240,7 +240,7 @@
         assertThat(cachedDevice1.getName()).isEqualTo(DEVICE_ALIAS_1);
 
         final String newAliasName = "NewAliasName";
-        when(mDevice1.getAliasName()).thenReturn(newAliasName);
+        when(mDevice1.getAlias()).thenReturn(newAliasName);
         mCachedDeviceManager.onDeviceNameUpdated(mDevice1);
         assertThat(cachedDevice1.getName()).isEqualTo(newAliasName);
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 5c89a01..53ff1a1 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -702,7 +702,7 @@
 
     @Test
     public void deviceName_testAliasNameAvailable() {
-        when(mDevice.getAliasName()).thenReturn(DEVICE_ALIAS);
+        when(mDevice.getAlias()).thenReturn(DEVICE_ALIAS);
         when(mDevice.getName()).thenReturn(DEVICE_NAME);
         CachedBluetoothDevice cachedBluetoothDevice =
                 new CachedBluetoothDevice(mContext, mProfileManager, mDevice);
@@ -725,7 +725,7 @@
     @Test
     public void deviceName_testRenameDevice() {
         final String[] alias = {DEVICE_ALIAS};
-        doAnswer(invocation -> alias[0]).when(mDevice).getAliasName();
+        doAnswer(invocation -> alias[0]).when(mDevice).getAlias();
         doAnswer(invocation -> {
             alias[0] = (String) invocation.getArguments()[0];
             return true;
@@ -842,14 +842,14 @@
 
     @Test
     public void getName_aliasNameNotNull_returnAliasName() {
-        when(mDevice.getAliasName()).thenReturn(DEVICE_NAME);
+        when(mDevice.getAlias()).thenReturn(DEVICE_NAME);
 
         assertThat(mCachedDevice.getName()).isEqualTo(DEVICE_NAME);
     }
 
     @Test
     public void getName_aliasNameIsNull_returnAddress() {
-        when(mDevice.getAliasName()).thenReturn(null);
+        when(mDevice.getAlias()).thenReturn(null);
 
         assertThat(mCachedDevice.getName()).isEqualTo(DEVICE_ADDRESS);
     }
@@ -857,7 +857,7 @@
     @Test
     public void setName_setDeviceNameIsNotNull() {
         final String name = "test name";
-        when(mDevice.getAliasName()).thenReturn(DEVICE_NAME);
+        when(mDevice.getAlias()).thenReturn(DEVICE_NAME);
 
         mCachedDevice.setName(name);
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
index 2b5466c..7be176a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
@@ -75,8 +75,8 @@
         when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2);
         when(mDevice1.getName()).thenReturn(DEVICE_NAME_1);
         when(mDevice2.getName()).thenReturn(DEVICE_NAME_2);
-        when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1);
-        when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2);
+        when(mDevice1.getAlias()).thenReturn(DEVICE_ALIAS_1);
+        when(mDevice2.getAlias()).thenReturn(DEVICE_ALIAS_2);
         when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS);
         when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS);
         when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/NavigationEdgeBackPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NavigationEdgeBackPlugin.java
new file mode 100644
index 0000000..bd86407
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NavigationEdgeBackPlugin.java
@@ -0,0 +1,60 @@
+/*
+ * 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.systemui.plugins;
+
+import android.graphics.Point;
+import android.view.MotionEvent;
+import android.view.WindowManager;
+
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+/** Plugin to handle navigation edge gestures for Back. */
+@ProvidesInterface(
+        action = NavigationEdgeBackPlugin.ACTION,
+        version = NavigationEdgeBackPlugin.VERSION)
+public interface NavigationEdgeBackPlugin extends Plugin {
+    String ACTION = "com.android.systemui.action.PLUGIN_NAVIGATION_EDGE_BACK_ACTION";
+    int VERSION = 1;
+
+
+    /** Specifies if the UI should be rendered on the left side of the screen. */
+    void setIsLeftPanel(boolean isLeftPanel);
+
+    /** Sets the insets for the gesture handling area. */
+    void setInsets(int leftInset, int rightInset);
+
+    /** Sets the display size. */
+    void setDisplaySize(Point displaySize);
+
+    /** Sets the callback that should be invoked when a Back gesture is detected. */
+    void setBackCallback(BackCallback callback);
+
+    /** Sets the base LayoutParams for the UI. */
+    void setLayoutParams(WindowManager.LayoutParams layoutParams);
+
+    /** Updates the UI based on the motion events passed in device coordinates. */
+    void onMotionEvent(MotionEvent motionEvent);
+
+    /** Callback to let the system react to the detected back gestures. */
+    interface BackCallback {
+        /** Indicates that a Back gesture was recognized and the system should go back. */
+        void triggerBack();
+
+        /** Indicates that the gesture was cancelled and the system should not go back. */
+        void cancelBack();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 741c95f..87fe3a2 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -103,14 +103,12 @@
         return Looper.getMainLooper();
     }
 
-    @Singleton
     @Provides
     @BgHandler
     public Handler provideBgHandler(@BgLooper Looper bgLooper) {
         return new Handler(bgLooper);
     }
 
-    @Singleton
     @Provides
     @MainHandler
     public Handler provideMainHandler(@MainLooper Looper mainLooper) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 94a1cf0..d377f1c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -319,7 +319,14 @@
             } else{
                 mColumns = mCellWidth == 0 ? 1 :
                         Math.min(maxTiles, availableWidth / mCellWidth );
-                mCellMarginHorizontal = (availableWidth - mColumns * mCellWidth) / (mColumns - 1);
+                // If we can only fit one column, use mCellMarginHorizontal to center it.
+                if (mColumns == 1) {
+                    mCellMarginHorizontal = (availableWidth - mCellWidth) / 2;
+                } else {
+                    mCellMarginHorizontal =
+                            (availableWidth - mColumns * mCellWidth) / (mColumns - 1);
+                }
+
             }
             return mColumns != prevNumColumns;
         }
@@ -357,6 +364,10 @@
 
         @Override
         protected int getColumnStart(int column) {
+            if (mColumns == 1) {
+                // Only one column/tile. Use the margin to center the tile.
+                return getPaddingStart() + mCellMarginHorizontal;
+            }
             return getPaddingStart() + column *  (mCellWidth + mCellMarginHorizontal);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java
index b21c65e..18574f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java
@@ -71,7 +71,7 @@
 
             ViewParent parent = view.getParent();
             StatusBarNotification statusBarNotification =
-                    getRowForParent(parent).getStatusBarNotification();
+                    getRowForParent(parent).getEntry().getSbn();
             final Intent intent = new Intent()
                     .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
                     .putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index ef40d98..0bfcdbd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
@@ -44,7 +44,7 @@
     private static  final DataExtractor sIconExtractor = new DataExtractor() {
         @Override
         public Object extractData(ExpandableNotificationRow row) {
-            return row.getStatusBarNotification().getNotification();
+            return row.getEntry().getSbn().getNotification();
         }
     };
     private static final IconComparator sIconVisibilityComparator = new IconComparator() {
@@ -207,7 +207,7 @@
         }
         // in case no view is visible we make sure the time is visible
         int timeVisibility = !hasVisibleText
-                || mRow.getStatusBarNotification().getNotification().showsTime()
+                || mRow.getEntry().getSbn().getNotification().showsTime()
                 ? View.VISIBLE : View.GONE;
         time.setVisibility(timeVisibility);
         View left = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index e10d27b..c556bc0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -216,7 +216,7 @@
         private StatusBarNotification getNotificationForParent(ViewParent parent) {
             while (parent != null) {
                 if (parent instanceof ExpandableNotificationRow) {
-                    return ((ExpandableNotificationRow) parent).getStatusBarNotification();
+                    return ((ExpandableNotificationRow) parent).getEntry().getSbn();
                 }
                 parent = parent.getParent();
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index ef733a9..4204f68 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -204,7 +204,7 @@
         }
 
         for (ExpandableNotificationRow viewToRemove : viewsToRemove) {
-            if (mGroupManager.isChildInGroupWithSummary(viewToRemove.getStatusBarNotification())) {
+            if (mGroupManager.isChildInGroupWithSummary(viewToRemove.getEntry().getSbn())) {
                 // we are only transferring this notification to its parent, don't generate an
                 // animation
                 mListContainer.setChildTransferInProgress(true);
@@ -339,7 +339,7 @@
                 for (ExpandableNotificationRow remove : toRemove) {
                     parent.removeChildNotification(remove);
                     if (mEntryManager.getActiveNotificationUnfiltered(
-                            remove.getStatusBarNotification().getKey()) == null) {
+                            remove.getEntry().getSbn().getKey()) == null) {
                         // We only want to add an animation if the view is completely removed
                         // otherwise it's just a transfer
                         mListContainer.notifyGroupChildRemoved(remove,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
index fd2f720..b5c6641 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
@@ -55,7 +55,7 @@
         mShadeController.wakeUpIfDozing(SystemClock.uptimeMillis(), v, "NOTIFICATION_CLICK");
 
         final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-        final StatusBarNotification sbn = row.getStatusBarNotification();
+        final StatusBarNotification sbn = row.getEntry().getSbn();
         if (sbn == null) {
             Log.e(TAG, "NotificationClicker called on an unclickable notification,");
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index f0d07a7..9ac5b44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -198,7 +198,6 @@
     private String mLoggingKey;
     private NotificationGuts mGuts;
     private NotificationEntry mEntry;
-    private StatusBarNotification mStatusBarNotification;
     private String mAppName;
 
     /**
@@ -261,10 +260,10 @@
         @Override
         public void onClick(View v) {
             if (!shouldShowPublic() && (!mIsLowPriority || isExpanded())
-                    && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
+                    && mGroupManager.isSummaryOfGroup(mEntry.getSbn())) {
                 mGroupExpansionChanging = true;
-                final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
-                boolean nowExpanded = mGroupManager.toggleGroupExpansion(mStatusBarNotification);
+                final boolean wasExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
+                boolean nowExpanded = mGroupManager.toggleGroupExpansion(mEntry.getSbn());
                 mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
                 MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
                         nowExpanded);
@@ -441,7 +440,6 @@
      */
     public void setEntry(@NonNull NotificationEntry entry) {
         mEntry = entry;
-        mStatusBarNotification = entry.getSbn();
         cacheIsSystemNotification();
     }
 
@@ -516,7 +514,7 @@
      */
     public boolean getIsNonblockable() {
         boolean isNonblockable = Dependency.get(NotificationBlockingHelperManager.class)
-                .isNonblockable(mStatusBarNotification.getPackageName(),
+                .isNonblockable(mEntry.getSbn().getPackageName(),
                         mEntry.getChannel().getId());
 
         // If the SystemNotifAsyncTask hasn't finished running or retrieved a value, we'll try once
@@ -526,7 +524,7 @@
                 Log.d(TAG, "Retrieving isSystemNotification on main thread");
             }
             mSystemNotificationAsyncTask.cancel(true /* mayInterruptIfRunning */);
-            mEntry.mIsSystemNotification = isSystemNotification(mContext, mStatusBarNotification);
+            mEntry.mIsSystemNotification = isSystemNotification(mContext, mEntry.getSbn());
         }
 
         isNonblockable |= mEntry.getChannel().isImportanceLockedByOEM();
@@ -547,11 +545,11 @@
         for (NotificationContentView l : mLayouts) {
             l.onNotificationUpdated(mEntry);
         }
-        mIsColorized = mStatusBarNotification.getNotification().isColorized();
+        mIsColorized = mEntry.getSbn().getNotification().isColorized();
         mShowingPublicInitialized = false;
         updateNotificationColor();
         if (mMenuRow != null) {
-            mMenuRow.onNotificationUpdated(mStatusBarNotification);
+            mMenuRow.onNotificationUpdated(mEntry.getSbn());
             mMenuRow.setAppName(mAppName);
         }
         if (mIsSummaryWithChildren) {
@@ -583,7 +581,7 @@
     /** Called when the notification's ranking was changed (but nothing else changed). */
     public void onNotificationRankingUpdated() {
         if (mMenuRow != null) {
-            mMenuRow.onNotificationUpdated(mStatusBarNotification);
+            mMenuRow.onNotificationUpdated(mEntry.getSbn());
         }
     }
 
@@ -676,10 +674,6 @@
         layout.setHeights(minHeight, headsUpHeight, mNotificationMaxHeight);
     }
 
-    public StatusBarNotification getStatusBarNotification() {
-        return mStatusBarNotification;
-    }
-
     public NotificationEntry getEntry() {
         return mEntry;
     }
@@ -807,7 +801,7 @@
      * @return whether this notification is the only child in the group summary
      */
     public boolean isOnlyChildInGroup() {
-        return mGroupManager.isOnlyChildInGroup(getStatusBarNotification());
+        return mGroupManager.isOnlyChildInGroup(mEntry.getSbn());
     }
 
     public ExpandableNotificationRow getNotificationParent() {
@@ -1181,7 +1175,7 @@
         }
 
         if (mMenuRow.getMenuView() == null) {
-            mMenuRow.createMenu(this, mStatusBarNotification);
+            mMenuRow.createMenu(this, mEntry.getSbn());
             mMenuRow.setAppName(mAppName);
             FrameLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
                     LayoutParams.MATCH_PARENT);
@@ -1222,7 +1216,7 @@
         if (oldMenu != null) {
             int menuIndex = indexOfChild(oldMenu);
             removeView(oldMenu);
-            mMenuRow.createMenu(ExpandableNotificationRow.this, mStatusBarNotification);
+            mMenuRow.createMenu(ExpandableNotificationRow.this, mEntry.getSbn());
             mMenuRow.setAppName(mAppName);
             addView(mMenuRow.getMenuView(), menuIndex);
         }
@@ -1230,7 +1224,7 @@
             l.initView();
             l.reInflateViews();
         }
-        mStatusBarNotification.clearPackageContext();
+        mEntry.getSbn().clearPackageContext();
         mNotificationInflater.clearCachesAndReInflate();
     }
 
@@ -1290,7 +1284,7 @@
                 == Configuration.UI_MODE_NIGHT_YES;
 
         mNotificationColor = ContrastColorUtil.resolveContrastColor(mContext,
-                getStatusBarNotification().getNotification().color,
+                mEntry.getSbn().getNotification().color,
                 getBackgroundColorWithoutTint(), nightMode);
     }
 
@@ -1438,7 +1432,7 @@
     public void performDismiss(boolean fromAccessibility) {
         if (isOnlyChildInGroup()) {
             NotificationEntry groupSummary =
-                    mGroupManager.getLogicalGroupSummary(getStatusBarNotification());
+                    mGroupManager.getLogicalGroupSummary(mEntry.getSbn());
             if (groupSummary.isClearable()) {
                 // If this is the only child in the group, dismiss the group, but don't try to show
                 // the blocking helper affordance!
@@ -2209,8 +2203,8 @@
         getFalsingManager().setNotificationExpanded();
         if (mIsSummaryWithChildren && !shouldShowPublic() && allowChildExpansion
                 && !mChildrenContainer.showingAsLowPriority()) {
-            final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
-            mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
+            final boolean wasExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
+            mGroupManager.setGroupExpanded(mEntry.getSbn(), userExpanded);
             onExpansionChanged(true /* userAction */, wasExpanded);
             return;
         }
@@ -2356,7 +2350,7 @@
 
     @Override
     public boolean isGroupExpanded() {
-        return mGroupManager.isGroupExpanded(mStatusBarNotification);
+        return mGroupManager.isGroupExpanded(mEntry.getSbn());
     }
 
     private void onChildrenCountChanged() {
@@ -2397,9 +2391,9 @@
             for (int i = 0; i < numChildren; i++) {
                 final ExpandableNotificationRow childRow = childrenRows.get(i);
                 final NotificationChannel childChannel = childRow.getEntry().getChannel();
-                final StatusBarNotification childSbn = childRow.getStatusBarNotification();
-                if (childSbn.getUser().equals(mStatusBarNotification.getUser()) &&
-                        childSbn.getPackageName().equals(mStatusBarNotification.getPackageName())) {
+                final StatusBarNotification childSbn = childRow.getEntry().getSbn();
+                if (childSbn.getUser().equals(mEntry.getSbn().getUser())
+                        && childSbn.getPackageName().equals(mEntry.getSbn().getPackageName())) {
                     channels.add(childChannel);
                 }
             }
@@ -2593,7 +2587,7 @@
     public void makeActionsVisibile() {
         setUserExpanded(true, true);
         if (isChildInGroup()) {
-            mGroupManager.setGroupExpanded(mStatusBarNotification, true);
+            mGroupManager.setGroupExpanded(mEntry.getSbn(), true);
         }
         notifyHeightChanged(false /* needsAnimation */);
     }
@@ -2890,7 +2884,7 @@
 
     public void onExpandedByGesture(boolean userExpanded) {
         int event = MetricsEvent.ACTION_NOTIFICATION_GESTURE_EXPANDER;
-        if (mGroupManager.isSummaryOfGroup(getStatusBarNotification())) {
+        if (mGroupManager.isSummaryOfGroup(mEntry.getSbn())) {
             event = MetricsEvent.ACTION_NOTIFICATION_GROUP_GESTURE_EXPANDER;
         }
         MetricsLogger.action(mContext, event, userExpanded);
@@ -2935,7 +2929,7 @@
     private void onExpansionChanged(boolean userAction, boolean wasExpanded) {
         boolean nowExpanded = isExpanded();
         if (mIsSummaryWithChildren && (!mIsLowPriority || wasExpanded)) {
-            nowExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
+            nowExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
         }
         if (nowExpanded != wasExpanded) {
             updateShelfIconColor();
@@ -3224,7 +3218,7 @@
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         super.dump(fd, pw, args);
-        pw.println("  Notification: " + getStatusBarNotification().getKey());
+        pw.println("  Notification: " + mEntry.getKey());
         pw.print("    visibility: " + getVisibility());
         pw.print(", alpha: " + getAlpha());
         pw.print(", translation: " + getTranslation());
@@ -3267,7 +3261,7 @@
 
         @Override
         protected Boolean doInBackground(Void... voids) {
-            return isSystemNotification(mContext, mStatusBarNotification);
+            return isSystemNotification(mContext, mEntry.getSbn());
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
index 37f63c9..7b758aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
@@ -166,7 +166,7 @@
     }
 
     private LogMaker getLogMaker() {
-        return mBlockingHelperRow.getStatusBarNotification()
+        return mBlockingHelperRow.getEntry().getSbn()
             .getLogMaker()
             .setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index a91a119..54dee8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -512,7 +512,7 @@
                     existingWrapper.onReinflated();
                 }
             } catch (Exception e) {
-                handleInflationError(runningInflations, e, row.getStatusBarNotification(), callback);
+                handleInflationError(runningInflations, e, row.getEntry().getSbn(), callback);
                 // Add a running inflation to make sure we don't trigger callbacks.
                 // Safe to do because only happens in tests.
                 runningInflations.put(inflationId, new CancellationSignal());
@@ -563,7 +563,7 @@
                     onViewApplied(newView);
                 } catch (Exception anotherException) {
                     runningInflations.remove(inflationId);
-                    handleInflationError(runningInflations, e, row.getStatusBarNotification(),
+                    handleInflationError(runningInflations, e, row.getEntry().getSbn(),
                             callback);
                 }
             }
@@ -838,7 +838,7 @@
 
         private void handleError(Exception e) {
             mRow.getEntry().onInflationTaskFinished();
-            StatusBarNotification sbn = mRow.getStatusBarNotification();
+            StatusBarNotification sbn = mRow.getEntry().getSbn();
             final String ident = sbn.getPackageName() + "/0x"
                     + Integer.toHexString(sbn.getId());
             Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index f67cd1b..77c0a46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -189,7 +189,7 @@
     @VisibleForTesting
     protected boolean bindGuts(final ExpandableNotificationRow row,
             NotificationMenuRowPlugin.MenuItem item) {
-        StatusBarNotification sbn = row.getStatusBarNotification();
+        StatusBarNotification sbn = row.getEntry().getSbn();
 
         row.setGutsView(item);
         row.setTag(sbn.getPackageName());
@@ -238,7 +238,7 @@
             final ExpandableNotificationRow row,
             NotificationSnooze notificationSnoozeView) {
         NotificationGuts guts = row.getGuts();
-        StatusBarNotification sbn = row.getStatusBarNotification();
+        StatusBarNotification sbn = row.getEntry().getSbn();
 
         notificationSnoozeView.setSnoozeListener(mListContainer.getSwipeActionHelper());
         notificationSnoozeView.setStatusBarNotification(sbn);
@@ -258,7 +258,7 @@
             final ExpandableNotificationRow row,
             AppOpsInfo appOpsInfoView) {
         NotificationGuts guts = row.getGuts();
-        StatusBarNotification sbn = row.getStatusBarNotification();
+        StatusBarNotification sbn = row.getEntry().getSbn();
         UserHandle userHandle = sbn.getUser();
         PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
                 userHandle.getIdentifier());
@@ -284,7 +284,7 @@
             final ExpandableNotificationRow row,
             NotificationInfo notificationInfoView) throws Exception {
         NotificationGuts guts = row.getGuts();
-        StatusBarNotification sbn = row.getStatusBarNotification();
+        StatusBarNotification sbn = row.getEntry().getSbn();
         String packageName = sbn.getPackageName();
         // Settings link is only valid for notifications that specify a non-system user
         NotificationInfo.OnSettingsClickListener onSettingsClick = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java
index 2da4d2c..7248bce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java
@@ -39,7 +39,7 @@
     @Override
     public void onContentUpdated(ExpandableNotificationRow row) {
         super.onContentUpdated(row);
-        updateImageTag(row.getStatusBarNotification());
+        updateImageTag(row.getEntry().getSbn());
     }
 
     private void updateImageTag(StatusBarNotification notification) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
index 4261df3..41f93cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
@@ -44,7 +44,7 @@
     public void onContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
-        resolveViews(row.getStatusBarNotification());
+        resolveViews(row.getEntry().getSbn());
         super.onContentUpdated(row);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 0b3871d..5e52c0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -125,7 +125,7 @@
         updateTransformedTypes();
         addRemainingTransformTypes();
         updateCropToPaddingForImageViews();
-        Notification notification = row.getStatusBarNotification().getNotification();
+        Notification notification = row.getEntry().getSbn().getNotification();
         mIcon.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
         // The work profile image is always the same lets just set the icon tag for it not to
         // animate
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 516d649..2a4b315 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -183,7 +183,7 @@
             QuickQSPanel panel = ctrl.getStatusBarView().findViewById(
                     com.android.systemui.R.id.quick_qs_panel);
             panel.getMediaPlayer().setMediaSession(token,
-                    mRow.getStatusBarNotification().getNotification().getSmallIcon(),
+                    mRow.getEntry().getSbn().getNotification().getSmallIcon(),
                     getNotificationHeader().getOriginalIconColor(),
                     mRow.getCurrentBackgroundTint(),
                     mActions,
@@ -191,11 +191,11 @@
             QSPanel bigPanel = ctrl.getStatusBarView().findViewById(
                     com.android.systemui.R.id.quick_settings_panel);
             bigPanel.addMediaSession(token,
-                    mRow.getStatusBarNotification().getNotification().getSmallIcon(),
+                    mRow.getEntry().getSbn().getNotification().getSmallIcon(),
                     getNotificationHeader().getOriginalIconColor(),
                     mRow.getCurrentBackgroundTint(),
                     mActions,
-                    mRow.getStatusBarNotification());
+                    mRow.getEntry().getSbn());
         }
 
         boolean showCompactSeekbar = mMediaManager.getShowCompactMediaSeekbar();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
index 97d8443..90ea6e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -286,7 +286,7 @@
     public void onContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
-        resolveTemplateViews(row.getStatusBarNotification());
+        resolveTemplateViews(row.getEntry().getSbn());
         super.onContentUpdated(row);
         if (row.getHeaderVisibleAmount() != DEFAULT_HEADER_VISIBLE_AMOUNT) {
             setHeaderVisibleAmount(row.getHeaderVisibleAmount());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 45f7b3a..75ceb0f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -299,7 +299,7 @@
 
     public void recreateNotificationHeader(OnClickListener listener) {
         mHeaderClickListener = listener;
-        StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
+        StatusBarNotification notification = mContainingNotification.getEntry().getSbn();
         final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
                 notification.getNotification());
         RemoteViews header = builder.makeNotificationHeader();
@@ -329,7 +329,7 @@
      */
     private void recreateLowPriorityHeader(Notification.Builder builder) {
         RemoteViews header;
-        StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
+        StatusBarNotification notification = mContainingNotification.getEntry().getSbn();
         if (mIsLowPriority) {
             if (builder == null) {
                 builder = Notification.Builder.recoverBuilder(getContext(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 462fa59..43af3aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1454,8 +1454,8 @@
         }
         ExpandableNotificationRow row = topEntry.getRow();
         if (row.isChildInGroup()) {
-            final NotificationEntry groupSummary
-                    = mGroupManager.getGroupSummary(row.getStatusBarNotification());
+            final NotificationEntry groupSummary =
+                    mGroupManager.getGroupSummary(row.getEntry().getSbn());
             if (groupSummary != null) {
                 row = groupSummary.getRow();
             }
@@ -2996,7 +2996,7 @@
     private boolean isChildInGroup(View child) {
         return child instanceof ExpandableNotificationRow
                 && mGroupManager.isChildInGroupWithSummary(
-                ((ExpandableNotificationRow) child).getStatusBarNotification());
+                ((ExpandableNotificationRow) child).getEntry().getSbn());
     }
 
     /**
@@ -3071,7 +3071,7 @@
         if (child instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) child;
             NotificationEntry groupSummary =
-                    mGroupManager.getGroupSummary(row.getStatusBarNotification());
+                    mGroupManager.getGroupSummary(row.getEntry().getSbn());
             if (groupSummary != null && groupSummary.getRow() != row) {
                 return row.getVisibility() == View.INVISIBLE;
             }
@@ -6134,7 +6134,7 @@
             }
             if (view instanceof ExpandableNotificationRow) {
                 ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-                mMetricsLogger.write(row.getStatusBarNotification().getLogMaker()
+                mMetricsLogger.write(row.getEntry().getSbn().getLogMaker()
                         .setCategory(MetricsEvent.ACTION_TOUCH_GEAR)
                         .setType(MetricsEvent.TYPE_ACTION)
                         );
@@ -6160,7 +6160,7 @@
         public void onMenuShown(View row) {
             if (row instanceof ExpandableNotificationRow) {
                 ExpandableNotificationRow notificationRow = (ExpandableNotificationRow) row;
-                mMetricsLogger.write(notificationRow.getStatusBarNotification().getLogMaker()
+                mMetricsLogger.write(notificationRow.getEntry().getSbn().getLogMaker()
                         .setCategory(MetricsEvent.ACTION_REVEAL_GEAR)
                         .setType(MetricsEvent.TYPE_ACTION));
                 mHeadsUpManager.setMenuShown(notificationRow.getEntry(), true);
@@ -6256,7 +6256,7 @@
                 ExpandableNotificationRow row = (ExpandableNotificationRow) view;
                 if (row.isHeadsUp()) {
                     mHeadsUpManager.addSwipedOutNotification(
-                            row.getStatusBarNotification().getKey());
+                            row.getEntry().getSbn().getKey());
                 }
                 isBlockingHelperShown =
                         row.performDismissWithBlockingHelper(false /* fromAccessibility */);
@@ -6327,9 +6327,9 @@
             if (animView instanceof ExpandableNotificationRow) {
                 ExpandableNotificationRow row = (ExpandableNotificationRow) animView;
                 if (row.isPinned() && !canChildBeDismissed(row)
-                        && row.getStatusBarNotification().getNotification().fullScreenIntent
+                        && row.getEntry().getSbn().getNotification().fullScreenIntent
                                 == null) {
-                    mHeadsUpManager.removeNotification(row.getStatusBarNotification().getKey(),
+                    mHeadsUpManager.removeNotification(row.getEntry().getSbn().getKey(),
                             true /* removeImmediately */);
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 1c8e832..8ee964f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -22,7 +22,6 @@
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.PointF;
-import android.graphics.Rect;
 import android.graphics.Region;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManager.DisplayListener;
@@ -32,9 +31,7 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.util.Log;
-import android.util.MathUtils;
 import android.util.StatsLog;
-import android.view.Gravity;
 import android.view.ISystemGestureExclusionListener;
 import android.view.InputChannel;
 import android.view.InputDevice;
@@ -44,7 +41,6 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
-import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
@@ -53,7 +49,10 @@
 import com.android.systemui.R;
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.model.SysUiState;
+import com.android.systemui.plugins.NavigationEdgeBackPlugin;
+import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.system.QuickStepContract;
 
 import java.io.PrintWriter;
@@ -62,7 +61,8 @@
 /**
  * Utility class to handle edge swipes for back gesture
  */
-public class EdgeBackGestureHandler implements DisplayListener {
+public class EdgeBackGestureHandler implements DisplayListener,
+        PluginListener<NavigationEdgeBackPlugin> {
 
     private static final String TAG = "EdgeBackGestureHandler";
     private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
@@ -85,6 +85,7 @@
 
     private final Context mContext;
     private final OverviewProxyService mOverviewProxyService;
+    private PluginManager mPluginManager;
 
     private final Point mDisplaySize = new Point();
     private final int mDisplayId;
@@ -100,14 +101,6 @@
     private final float mTouchSlop;
     // Duration after which we consider the event as longpress.
     private final int mLongPressTimeout;
-    // The threshold where the touch needs to be at most, such that the arrow is displayed above the
-    // finger, otherwise it will be below
-    private final int mMinArrowPosition;
-    // The amount by which the arrow is shifted to avoid the finger
-    private final int mFingerOffset;
-
-
-    private final int mNavBarHeight;
 
     private final PointF mDownPoint = new PointF();
     private boolean mThresholdCrossed = false;
@@ -123,24 +116,49 @@
     private InputMonitor mInputMonitor;
     private InputEventReceiver mInputEventReceiver;
 
-    private final WindowManager mWm;
-
-    private NavigationBarEdgePanel mEdgePanel;
-    private WindowManager.LayoutParams mEdgePanelLp;
-    private final Rect mSamplingRect = new Rect();
-    private RegionSamplingHelper mRegionSamplingHelper;
+    private NavigationEdgeBackPlugin mEdgeBackPlugin;
     private int mLeftInset;
     private int mRightInset;
     private int mSysUiFlags;
 
+    private final NavigationEdgeBackPlugin.BackCallback mBackCallback =
+            new NavigationEdgeBackPlugin.BackCallback() {
+                @Override
+                public void triggerBack() {
+                    sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
+                    sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
+
+                    mOverviewProxyService.notifyBackAction(true, (int) mDownPoint.x,
+                            (int) mDownPoint.y, false /* isButton */, !mIsOnLeftEdge);
+                    int backtype = (mInRejectedExclusion
+                            ? StatsLog.BACK_GESTURE__TYPE__COMPLETED_REJECTED :
+                            StatsLog.BACK_GESTURE__TYPE__COMPLETED);
+                    StatsLog.write(StatsLog.BACK_GESTURE_REPORTED_REPORTED, backtype,
+                            (int) mDownPoint.y, mIsOnLeftEdge
+                                    ? StatsLog.BACK_GESTURE__X_LOCATION__LEFT :
+                                    StatsLog.BACK_GESTURE__X_LOCATION__RIGHT);
+                }
+
+                @Override
+                public void cancelBack() {
+                    mOverviewProxyService.notifyBackAction(false, (int) mDownPoint.x,
+                            (int) mDownPoint.y, false /* isButton */, !mIsOnLeftEdge);
+                    int backtype = StatsLog.BACK_GESTURE__TYPE__INCOMPLETE;
+                    StatsLog.write(StatsLog.BACK_GESTURE_REPORTED_REPORTED, backtype,
+                            (int) mDownPoint.y, mIsOnLeftEdge
+                                    ? StatsLog.BACK_GESTURE__X_LOCATION__LEFT :
+                                    StatsLog.BACK_GESTURE__X_LOCATION__RIGHT);
+                }
+            };
+
     public EdgeBackGestureHandler(Context context, OverviewProxyService overviewProxyService,
-            SysUiState sysUiFlagContainer) {
+            SysUiState sysUiFlagContainer, PluginManager pluginManager) {
         final Resources res = context.getResources();
         mContext = context;
         mDisplayId = context.getDisplayId();
         mMainExecutor = context.getMainExecutor();
-        mWm = context.getSystemService(WindowManager.class);
         mOverviewProxyService = overviewProxyService;
+        mPluginManager = pluginManager;
 
         // Reduce the default touch slop to ensure that we can intercept the gesture
         // before the app starts to react to it.
@@ -149,9 +167,6 @@
         mLongPressTimeout = Math.min(MAX_LONG_PRESS_TIMEOUT,
                 ViewConfiguration.getLongPressTimeout());
 
-        mNavBarHeight = res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height);
-        mMinArrowPosition = res.getDimensionPixelSize(R.dimen.navigation_edge_arrow_min_y);
-        mFingerOffset = res.getDimensionPixelSize(R.dimen.navigation_edge_finger_offset);
         updateCurrentUserResources(res);
         sysUiFlagContainer.addCallback(sysUiFlags -> mSysUiFlags = sysUiFlags);
     }
@@ -206,15 +221,14 @@
         mIsEnabled = isEnabled;
         disposeInputChannel();
 
-        if (mEdgePanel != null) {
-            mWm.removeView(mEdgePanel);
-            mEdgePanel = null;
-            mRegionSamplingHelper.stop();
-            mRegionSamplingHelper = null;
+        if (mEdgeBackPlugin != null) {
+            mEdgeBackPlugin.onDestroy();
+            mEdgeBackPlugin = null;
         }
 
         if (!mIsEnabled) {
             mContext.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
+            mPluginManager.removePluginListener(this);
 
             try {
                 WindowManagerGlobal.getWindowManagerService()
@@ -244,41 +258,51 @@
                     mInputMonitor.getInputChannel(), Looper.getMainLooper());
 
             // Add a nav bar panel window
-            mEdgePanel = new NavigationBarEdgePanel(mContext);
-            mEdgePanelLp = new WindowManager.LayoutParams(
-                    mContext.getResources()
-                            .getDimensionPixelSize(R.dimen.navigation_edge_panel_width),
-                    mContext.getResources()
-                            .getDimensionPixelSize(R.dimen.navigation_edge_panel_height),
-                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
-                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                            | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                            | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
-                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
-                    PixelFormat.TRANSLUCENT);
-            mEdgePanelLp.privateFlags |=
-                    WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
-            mEdgePanelLp.setTitle(TAG + mDisplayId);
-            mEdgePanelLp.accessibilityTitle = mContext.getString(R.string.nav_bar_edge_panel);
-            mEdgePanelLp.windowAnimations = 0;
-            mEdgePanel.setLayoutParams(mEdgePanelLp);
-            mWm.addView(mEdgePanel, mEdgePanelLp);
-            mRegionSamplingHelper = new RegionSamplingHelper(mEdgePanel,
-                    new RegionSamplingHelper.SamplingCallback() {
-                        @Override
-                        public void onRegionDarknessChanged(boolean isRegionDark) {
-                            mEdgePanel.setIsDark(!isRegionDark, true /* animate */);
-                        }
-
-                        @Override
-                        public Rect getSampledRegion(View sampledView) {
-                            return mSamplingRect;
-                        }
-                    });
-            mRegionSamplingHelper.setWindowVisible(true);
+            setEdgeBackPlugin(new NavigationBarEdgePanel(mContext));
+            mPluginManager.addPluginListener(
+                    this, NavigationEdgeBackPlugin.class, /*allowMultiple=*/ false);
         }
     }
 
+    @Override
+    public void onPluginConnected(NavigationEdgeBackPlugin plugin, Context context) {
+        setEdgeBackPlugin(plugin);
+    }
+
+    @Override
+    public void onPluginDisconnected(NavigationEdgeBackPlugin plugin) {
+        setEdgeBackPlugin(new NavigationBarEdgePanel(mContext));
+    }
+
+    private void setEdgeBackPlugin(NavigationEdgeBackPlugin edgeBackPlugin) {
+        if (mEdgeBackPlugin != null) {
+            mEdgeBackPlugin.onDestroy();
+        }
+        mEdgeBackPlugin = edgeBackPlugin;
+        mEdgeBackPlugin.setBackCallback(mBackCallback);
+        mEdgeBackPlugin.setLayoutParams(createLayoutParams());
+        updateDisplaySize();
+    }
+
+    private WindowManager.LayoutParams createLayoutParams() {
+        Resources resources = mContext.getResources();
+        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
+                resources.getDimensionPixelSize(R.dimen.navigation_edge_panel_width),
+                resources.getDimensionPixelSize(R.dimen.navigation_edge_panel_height),
+                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+                        | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+                PixelFormat.TRANSLUCENT);
+        layoutParams.privateFlags |=
+                WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+        layoutParams.setTitle(TAG + mContext.getDisplayId());
+        layoutParams.accessibilityTitle = mContext.getString(R.string.nav_bar_edge_panel);
+        layoutParams.windowAnimations = 0;
+        return layoutParams;
+    }
+
     private void onInputEvent(InputEvent ev) {
         if (ev instanceof MotionEvent) {
             onMotionEvent((MotionEvent) ev);
@@ -316,7 +340,7 @@
         mInRejectedExclusion = false;
         MotionEvent cancelEv = MotionEvent.obtain(ev);
         cancelEv.setAction(MotionEvent.ACTION_CANCEL);
-        mEdgePanel.handleTouch(cancelEv);
+        mEdgeBackPlugin.onMotionEvent(cancelEv);
         cancelEv.recycle();
     }
 
@@ -330,14 +354,8 @@
             mAllowGesture = !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
                     && isWithinTouchRegion((int) ev.getX(), (int) ev.getY());
             if (mAllowGesture) {
-                mEdgePanelLp.gravity = mIsOnLeftEdge
-                        ? (Gravity.LEFT | Gravity.TOP)
-                        : (Gravity.RIGHT | Gravity.TOP);
-                mEdgePanel.setIsLeftPanel(mIsOnLeftEdge);
-                mEdgePanel.handleTouch(ev);
-                updateEdgePanelPosition(ev.getY());
-                mWm.updateViewLayout(mEdgePanel, mEdgePanelLp);
-                mRegionSamplingHelper.start(mSamplingRect);
+                mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
+                mEdgeBackPlugin.onMotionEvent(ev);
 
                 mDownPoint.set(ev.getX(), ev.getY());
                 mThresholdCrossed = false;
@@ -369,53 +387,10 @@
             }
 
             // forward touch
-            mEdgePanel.handleTouch(ev);
-
-            boolean isUp = action == MotionEvent.ACTION_UP;
-            if (isUp) {
-                boolean performAction = mEdgePanel.shouldTriggerBack();
-                if (performAction) {
-                    // Perform back
-                    sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
-                    sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
-                }
-                mOverviewProxyService.notifyBackAction(performAction, (int) mDownPoint.x,
-                        (int) mDownPoint.y, false /* isButton */, !mIsOnLeftEdge);
-                int backtype = performAction ? (mInRejectedExclusion
-                        ? StatsLog.BACK_GESTURE__TYPE__COMPLETED_REJECTED :
-                                StatsLog.BACK_GESTURE__TYPE__COMPLETED) :
-                                        StatsLog.BACK_GESTURE__TYPE__INCOMPLETE;
-                StatsLog.write(StatsLog.BACK_GESTURE_REPORTED_REPORTED, backtype,
-                        (int) mDownPoint.y, mIsOnLeftEdge
-                                ? StatsLog.BACK_GESTURE__X_LOCATION__LEFT :
-                                StatsLog.BACK_GESTURE__X_LOCATION__RIGHT);
-            }
-            if (isUp || action == MotionEvent.ACTION_CANCEL) {
-                mRegionSamplingHelper.stop();
-            } else {
-                updateSamplingRect();
-                mRegionSamplingHelper.updateSamplingRect();
-            }
+            mEdgeBackPlugin.onMotionEvent(ev);
         }
     }
 
-    private void updateEdgePanelPosition(float touchY) {
-        float position = touchY - mFingerOffset;
-        position = Math.max(position, mMinArrowPosition);
-        position = (position - mEdgePanelLp.height / 2.0f);
-        mEdgePanelLp.y = MathUtils.constrain((int) position, 0, mDisplaySize.y);
-        updateSamplingRect();
-    }
-
-    private void updateSamplingRect() {
-        int top = mEdgePanelLp.y;
-        int left = mIsOnLeftEdge ? mLeftInset : mDisplaySize.x - mRightInset - mEdgePanelLp.width;
-        int right = left + mEdgePanelLp.width;
-        int bottom = top + mEdgePanelLp.height;
-        mSamplingRect.set(left, top, right, bottom);
-        mEdgePanel.adjustRectToBoundingBox(mSamplingRect);
-    }
-
     @Override
     public void onDisplayAdded(int displayId) { }
 
@@ -433,6 +408,9 @@
         mContext.getSystemService(DisplayManager.class)
                 .getDisplay(mDisplayId)
                 .getRealSize(mDisplaySize);
+        if (mEdgeBackPlugin != null) {
+            mEdgeBackPlugin.setDisplaySize(mDisplaySize);
+        }
     }
 
     private void sendEvent(int action, int code) {
@@ -454,6 +432,9 @@
     public void setInsets(int leftInset, int rightInset) {
         mLeftInset = leftInset;
         mRightInset = rightInset;
+        if (mEdgeBackPlugin != null) {
+            mEdgeBackPlugin.setInsets(leftInset, rightInset);
+        }
     }
 
     public void dump(PrintWriter pw) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index 7f31f3d..ac06d9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -132,7 +132,7 @@
                 if (mPickedChild != null && mTouchingHeadsUpView) {
                     // We may swallow this click if the heads up just came in.
                     if (mHeadsUpManager.shouldSwallowClick(
-                            mPickedChild.getStatusBarNotification().getKey())) {
+                            mPickedChild.getEntry().getSbn().getKey())) {
                         endMotion();
                         return true;
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
index 4f223c3..2357309 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
@@ -19,34 +19,40 @@
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.graphics.Canvas;;
+import android.content.res.Resources;
+import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Path;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.os.VibrationEffect;
-import android.util.DisplayMetrics;
 import android.util.MathUtils;
 import android.view.ContextThemeWrapper;
+import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
+import android.view.WindowManager;
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
 
-import com.android.settingslib.Utils;
-import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.VibratorHelper;
-
 import androidx.core.graphics.ColorUtils;
 import androidx.dynamicanimation.animation.DynamicAnimation;
 import androidx.dynamicanimation.animation.FloatPropertyCompat;
 import androidx.dynamicanimation.animation.SpringAnimation;
 import androidx.dynamicanimation.animation.SpringForce;
 
-public class NavigationBarEdgePanel extends View {
+import com.android.settingslib.Utils;
+import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.plugins.NavigationEdgeBackPlugin;
+import com.android.systemui.statusbar.VibratorHelper;
+
+public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPlugin {
+
+    private static final String TAG = "NavigationBarEdgePanel";
 
     private static final long COLOR_ANIMATION_DURATION_MS = 120;
     private static final long DISAPPEAR_FADE_ANIMATION_DURATION_MS = 80;
@@ -114,6 +120,7 @@
     private static final Interpolator RUBBER_BAND_INTERPOLATOR_APPEAR
             = new PathInterpolator(1.0f / RUBBER_BAND_AMOUNT_APPEAR, 1.0f, 1.0f, 1.0f);
 
+    private final WindowManager mWindowManager;
     private final VibratorHelper mVibratorHelper;
 
     /**
@@ -134,9 +141,14 @@
      * The minimum delta needed in movement for the arrow to change direction / stop triggering back
      */
     private final float mMinDeltaForSwitch;
+    // The closest to y = 0 that the arrow will be displayed.
+    private int mMinArrowPosition;
+    // The amount the arrow is shifted to avoid the finger.
+    private int mFingerOffset;
 
     private final float mSwipeThreshold;
     private final Path mArrowPath = new Path();
+    private final Point mDisplaySize = new Point();
 
     private final SpringAnimation mAngleAnimation;
     private final SpringAnimation mTranslationAnimation;
@@ -158,6 +170,11 @@
     private int mArrowColorDark;
     private int mProtectionColor;
     private int mArrowColor;
+    private RegionSamplingHelper mRegionSamplingHelper;
+    private final Rect mSamplingRect = new Rect();
+    private WindowManager.LayoutParams mLayoutParams;
+    private int mLeftInset;
+    private int mRightInset;
 
     /**
      * True if the panel is currently on the left of the screen
@@ -242,10 +259,12 @@
                     return object.getVerticalTranslation();
                 }
             };
+    private BackCallback mBackCallback;
 
     public NavigationBarEdgePanel(Context context) {
         super(context);
 
+        mWindowManager = context.getSystemService(WindowManager.class);
         mVibratorHelper = Dependency.get(VibratorHelper.class);
 
         mDensity = context.getResources().getDisplayMetrics().density;
@@ -263,13 +282,10 @@
 
         mArrowColorAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
         mArrowColorAnimator.setDuration(COLOR_ANIMATION_DURATION_MS);
-        mArrowColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                int newColor = ColorUtils.blendARGB(mArrowStartColor, mArrowColor,
-                        animation.getAnimatedFraction());
-                setCurrentArrowColor(newColor);
-            }
+        mArrowColorAnimator.addUpdateListener(animation -> {
+            int newColor = ColorUtils.blendARGB(
+                    mArrowStartColor, mArrowColor, animation.getAnimatedFraction());
+            setCurrentArrowColor(newColor);
         });
 
         mArrowDisappearAnimation = ValueAnimator.ofFloat(0.0f, 1.0f);
@@ -317,6 +333,27 @@
         mSwipeThreshold = context.getResources()
                 .getDimension(R.dimen.navigation_edge_action_drag_threshold);
         setVisibility(GONE);
+
+        mRegionSamplingHelper = new RegionSamplingHelper(this,
+                new RegionSamplingHelper.SamplingCallback() {
+                    @Override
+                    public void onRegionDarknessChanged(boolean isRegionDark) {
+                        setIsDark(!isRegionDark, true /* animate */);
+                    }
+
+                    @Override
+                    public Rect getSampledRegion(View sampledView) {
+                        return mSamplingRect;
+                    }
+                });
+        mRegionSamplingHelper.setWindowVisible(true);
+    }
+
+    @Override
+    public void onDestroy() {
+        mWindowManager.removeView(this);
+        mRegionSamplingHelper.stop();
+        mRegionSamplingHelper = null;
     }
 
     @Override
@@ -324,30 +361,51 @@
         return false;
     }
 
-    public boolean shouldTriggerBack() {
-        return mTriggerBack;
-    }
-
-    public void setIsDark(boolean isDark, boolean animate) {
+    private void setIsDark(boolean isDark, boolean animate) {
         mIsDark = isDark;
         updateIsDark(animate);
     }
 
-    public void setShowProtection(boolean showProtection) {
+    private void setShowProtection(boolean showProtection) {
         mShowProtection = showProtection;
         invalidate();
     }
 
+    @Override
     public void setIsLeftPanel(boolean isLeftPanel) {
         mIsLeftPanel = isLeftPanel;
+        mLayoutParams.gravity = mIsLeftPanel
+                ? (Gravity.LEFT | Gravity.TOP)
+                : (Gravity.RIGHT | Gravity.TOP);
+    }
+
+    @Override
+    public void setInsets(int leftInset, int rightInset) {
+        mLeftInset = leftInset;
+        mRightInset = rightInset;
+    }
+
+    @Override
+    public void setDisplaySize(Point displaySize) {
+        mDisplaySize.set(displaySize.x, displaySize.y);
+        mScreenSize = Math.min(mDisplaySize.x, mDisplaySize.y);
+    }
+
+    @Override
+    public void setBackCallback(BackCallback callback) {
+        mBackCallback = callback;
+    }
+
+    @Override
+    public void setLayoutParams(WindowManager.LayoutParams layoutParams) {
+        mLayoutParams = layoutParams;
+        mWindowManager.addView(this, mLayoutParams);
     }
 
     /**
-     * Adjust the rect to conform the the actual visible bounding box of the arrow.
-     *
-     * @param samplingRect the existing bounding box in screen coordinates, to be modified
+     * Adjusts the sampling rect to conform to the actual visible bounding box of the arrow.
      */
-    public void adjustRectToBoundingBox(Rect samplingRect) {
+    private void adjustSamplingRectToBoundingBox() {
         float translation = mDesiredTranslation;
         if (!mTriggerBack) {
             // Let's take the resting position and bounds as the sampling rect, since we are not
@@ -361,7 +419,7 @@
             }
         }
         float left = translation - mArrowThickness / 2.0f;
-        left = mIsLeftPanel ? left : samplingRect.width() - left;
+        left = mIsLeftPanel ? left : mSamplingRect.width() - left;
 
         // Let's calculate the position of the end based on the angle
         float width = getStaticArrowWidth();
@@ -371,49 +429,49 @@
         }
 
         float top = (getHeight() * 0.5f) + mDesiredVerticalTranslation - height / 2.0f;
-        samplingRect.offset((int) left, (int) top);
-        samplingRect.set(samplingRect.left, samplingRect.top,
-                (int) (samplingRect.left + width),
-                (int) (samplingRect.top + height));
+        mSamplingRect.offset((int) left, (int) top);
+        mSamplingRect.set(mSamplingRect.left, mSamplingRect.top,
+                (int) (mSamplingRect.left + width),
+                (int) (mSamplingRect.top + height));
+        mRegionSamplingHelper.updateSamplingRect();
     }
 
-    /**
-     * Updates the UI based on the motion events passed in device co-ordinates
-     */
-    public void handleTouch(MotionEvent event) {
+    @Override
+    public void onMotionEvent(MotionEvent event) {
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
         }
         mVelocityTracker.addMovement(event);
         switch (event.getActionMasked()) {
-            case MotionEvent.ACTION_DOWN : {
+            case MotionEvent.ACTION_DOWN:
                 mDragSlopPassed = false;
                 resetOnDown();
                 mStartX = event.getX();
                 mStartY = event.getY();
                 setVisibility(VISIBLE);
+                updatePosition(event.getY());
+                mRegionSamplingHelper.start(mSamplingRect);
+                mWindowManager.updateViewLayout(this, mLayoutParams);
                 break;
-            }
-            case MotionEvent.ACTION_MOVE: {
+            case MotionEvent.ACTION_MOVE:
                 handleMoveEvent(event);
                 break;
-            }
-            // Fall through
             case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL: {
                 if (mTriggerBack) {
                     triggerBack();
                 } else {
-                    if (mTranslationAnimation.isRunning()) {
-                        mTranslationAnimation.addEndListener(mSetGoneEndListener);
-                    } else {
-                        setVisibility(GONE);
-                    }
+                    cancelBack();
                 }
+                mRegionSamplingHelper.stop();
                 mVelocityTracker.recycle();
                 mVelocityTracker = null;
                 break;
-            }
+            case MotionEvent.ACTION_CANCEL:
+                cancelBack();
+                mRegionSamplingHelper.stop();
+                mVelocityTracker.recycle();
+                mVelocityTracker = null;
+                break;
         }
     }
 
@@ -452,10 +510,10 @@
     }
 
     private void loadDimens() {
-        mArrowPaddingEnd = getContext().getResources().getDimensionPixelSize(
-                R.dimen.navigation_edge_panel_padding);
-        DisplayMetrics metrics = getResources().getDisplayMetrics();
-        mScreenSize = Math.min(metrics.widthPixels, metrics.heightPixels);
+        Resources res = getResources();
+        mArrowPaddingEnd = res.getDimensionPixelSize(R.dimen.navigation_edge_panel_padding);
+        mMinArrowPosition = res.getDimensionPixelSize(R.dimen.navigation_edge_arrow_min_y);
+        mFingerOffset = res.getDimensionPixelSize(R.dimen.navigation_edge_finger_offset);
     }
 
     private void updateArrowDirection() {
@@ -531,6 +589,11 @@
     }
 
     private void triggerBack() {
+        mBackCallback.triggerBack();
+
+        if (mVelocityTracker == null) {
+            mVelocityTracker = VelocityTracker.obtain();
+        }
         mVelocityTracker.computeCurrentVelocity(1000);
         // Only do the extra translation if we're not already flinging
         boolean isSlow = Math.abs(mVelocityTracker.getXVelocity()) < 500;
@@ -573,7 +636,16 @@
         } else {
             translationEnd.run();
         }
+    }
 
+    private void cancelBack() {
+        mBackCallback.cancelBack();
+
+        if (mTranslationAnimation.isRunning()) {
+            mTranslationAnimation.addEndListener(mSetGoneEndListener);
+        } else {
+            setVisibility(GONE);
+        }
     }
 
     private void resetOnDown() {
@@ -680,6 +752,24 @@
         float verticalTranslation = RUBBER_BAND_INTERPOLATOR.getInterpolation(progress)
                 * maxYOffset * Math.signum(yOffset);
         setDesiredVerticalTransition(verticalTranslation, true /* animated */);
+        updateSamplingRect();
+    }
+
+    private void updatePosition(float touchY) {
+        float position = touchY - mFingerOffset;
+        position = Math.max(position, mMinArrowPosition);
+        position -= mLayoutParams.height / 2.0f;
+        mLayoutParams.y = MathUtils.constrain((int) position, 0, mDisplaySize.y);
+        updateSamplingRect();
+    }
+
+    private void updateSamplingRect() {
+        int top = mLayoutParams.y;
+        int left = mIsLeftPanel ? mLeftInset : mDisplaySize.x - mRightInset - mLayoutParams.width;
+        int right = left + mLayoutParams.width;
+        int bottom = top + mLayoutParams.height;
+        mSamplingRect.set(left, top, right, bottom);
+        adjustSamplingRectToBoundingBox();
     }
 
     private void setDesiredVerticalTransition(float verticalTranslation, boolean animated) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index d3c7940..5a1b20d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -72,6 +72,7 @@
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsOnboarding;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -96,6 +97,7 @@
     private final RegionSamplingHelper mRegionSamplingHelper;
     private final int mNavColorSampleMargin;
     private final SysUiState mSysUiFlagContainer;
+    private final PluginManager mPluginManager;
 
     View mCurrentView = null;
     private View mVertical;
@@ -272,6 +274,7 @@
         boolean isGesturalMode = isGesturalMode(mNavBarMode);
 
         mSysUiFlagContainer = Dependency.get(SysUiState.class);
+        mPluginManager = Dependency.get(PluginManager.class);
         // Set up the context group of buttons
         mContextualButtonGroup = new ContextualButtonGroup(R.id.menu_container);
         final ContextualButton imeSwitcherButton = new ContextualButton(R.id.ime_switcher,
@@ -315,8 +318,8 @@
 
         mNavColorSampleMargin = getResources()
                         .getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin);
-        mEdgeBackGestureHandler =
-                new EdgeBackGestureHandler(context, mOverviewProxyService, mSysUiFlagContainer);
+        mEdgeBackGestureHandler = new EdgeBackGestureHandler(
+                context, mOverviewProxyService, mSysUiFlagContainer, mPluginManager);
         mRegionSamplingHelper = new RegionSamplingHelper(this,
                 new RegionSamplingHelper.SamplingCallback() {
                     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 8ebf574..35407c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -986,7 +986,7 @@
             }
             ExpandableNotificationRow row = (ExpandableNotificationRow) child;
             boolean suppressedSummary = mGroupManager != null
-                    && mGroupManager.isSummaryOfSuppressedGroup(row.getStatusBarNotification());
+                    && mGroupManager.isSummaryOfSuppressedGroup(row.getEntry().getSbn());
             if (suppressedSummary) {
                 continue;
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index b5a7847..322b23f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -175,7 +175,7 @@
         } else {
             if (row.isChildInGroup() && !row.areChildrenExpanded()) {
                 // The group isn't expanded, let's make sure it's visible!
-                mGroupManager.toggleGroupExpansion(row.getStatusBarNotification());
+                mGroupManager.toggleGroupExpansion(row.getEntry().getSbn());
             }
             row.setUserExpanded(true);
             row.getPrivateLayout().setOnExpandedVisibleListener(clickedView::performClick);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
index c1328ec..6d6a1fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
@@ -188,6 +188,7 @@
                 boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP;
                 boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;
 
+                boolean expandingBelowNotch = mExpandingBelowNotch;
                 if (isUp || isCancel) {
                     mExpandingBelowNotch = false;
                 }
@@ -236,8 +237,9 @@
                 // regular view bounds.
                 if (isDown && ev.getY() >= mView.getBottom()) {
                     mExpandingBelowNotch = true;
+                    expandingBelowNotch = true;
                 }
-                if (mExpandingBelowNotch) {
+                if (expandingBelowNotch) {
                     return mStatusBarView.dispatchTouchEvent(ev);
                 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index f0f9420..dc80906 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -33,13 +33,13 @@
 import com.android.settingslib.fuelgauge.BatterySaverUtils;
 import com.android.settingslib.fuelgauge.Estimate;
 import com.android.settingslib.utils.PowerUtil;
-import com.android.systemui.Dependency;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.MainHandler;
 import com.android.systemui.power.EnhancedEstimates;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.text.NumberFormat;
 import java.util.ArrayList;
 
 import javax.inject.Inject;
@@ -53,42 +53,39 @@
 public class BatteryControllerImpl extends BroadcastReceiver implements BatteryController {
     private static final String TAG = "BatteryController";
 
-    public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
+    private static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
 
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final int UPDATE_GRANULARITY_MSEC = 1000 * 60;
 
     private final EnhancedEstimates mEstimates;
     private final BroadcastDispatcher mBroadcastDispatcher;
-    private final ArrayList<BatteryController.BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
+    private final ArrayList<BatteryController.BatteryStateChangeCallback>
+            mChangeCallbacks = new ArrayList<>();
     private final ArrayList<EstimateFetchCompletion> mFetchCallbacks = new ArrayList<>();
     private final PowerManager mPowerManager;
-    private final Handler mHandler;
+    private final Handler mMainHandler;
+    private final Handler mBgHandler;
     private final Context mContext;
 
-    protected int mLevel;
-    protected boolean mPluggedIn;
-    protected boolean mCharging;
-    protected boolean mCharged;
-    protected boolean mPowerSave;
-    protected boolean mAodPowerSave;
+    private int mLevel;
+    private boolean mPluggedIn;
+    private boolean mCharging;
+    private boolean mCharged;
+    private boolean mPowerSave;
+    private boolean mAodPowerSave;
     private boolean mTestmode = false;
     private boolean mHasReceivedBattery = false;
     private Estimate mEstimate;
     private boolean mFetchingEstimate = false;
 
-    @Inject
-    public BatteryControllerImpl(Context context, EnhancedEstimates enhancedEstimates,
-            BroadcastDispatcher broadcastDispatcher) {
-        this(context, enhancedEstimates, context.getSystemService(PowerManager.class),
-                broadcastDispatcher);
-    }
-
     @VisibleForTesting
+    @Inject
     BatteryControllerImpl(Context context, EnhancedEstimates enhancedEstimates,
-            PowerManager powerManager, BroadcastDispatcher broadcastDispatcher) {
+            PowerManager powerManager, BroadcastDispatcher broadcastDispatcher,
+            @MainHandler Handler mainHandler, @BgHandler Handler bgHandler) {
         mContext = context;
-        mHandler = new Handler();
+        mMainHandler = mainHandler;
+        mBgHandler = bgHandler;
         mPowerManager = powerManager;
         mEstimates = enhancedEstimates;
         mBroadcastDispatcher = broadcastDispatcher;
@@ -162,7 +159,7 @@
             setPowerSave(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false));
         } else if (action.equals(ACTION_LEVEL_TEST)) {
             mTestmode = true;
-            mHandler.post(new Runnable() {
+            mMainHandler.post(new Runnable() {
                 int curLevel = 0;
                 int incr = 1;
                 int saveLevel = mLevel;
@@ -189,7 +186,7 @@
                     if (curLevel == 100) {
                         incr *= -1;
                     }
-                    mHandler.postDelayed(this, 200);
+                    mMainHandler.postDelayed(this, 200);
                 }
             });
         }
@@ -222,7 +219,6 @@
                 return null;
             }
 
-            String percentage = NumberFormat.getPercentInstance().format((double) mLevel / 100.0);
             return PowerUtil.getBatteryRemainingShortStringFormatted(
                     mContext, mEstimate.getEstimateMillis());
         }
@@ -235,7 +231,7 @@
         }
 
         mFetchingEstimate = true;
-        Dependency.get(Dependency.BG_HANDLER).post(() -> {
+        mBgHandler.post(() -> {
             // Only fetch the estimate if they are enabled
             synchronized (mFetchCallbacks) {
                 mEstimate = null;
@@ -244,7 +240,7 @@
                 }
             }
             mFetchingEstimate = false;
-            Dependency.get(Dependency.MAIN_HANDLER).post(this::notifyEstimateFetchCallbacks);
+            mMainHandler.post(this::notifyEstimateFetchCallbacks);
         });
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 99c94ac..46a8dad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -117,7 +117,7 @@
     private NotificationEntry createEntry() throws Exception {
         ExpandableNotificationRow row = mHelper.createRow();
         NotificationEntry entry = new NotificationEntryBuilder()
-                .setSbn(row.getStatusBarNotification())
+                .setSbn(row.getEntry().getSbn())
                 .build();
         entry.setRow(row);
         return entry;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
index 7326cd4..a25af84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
@@ -34,7 +34,6 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.util.ArrayMap;
-import android.util.Log;
 
 import androidx.test.filters.SmallTest;
 
@@ -121,7 +120,7 @@
         addNotif(6, PACKAGE_1).setRank(0);
         dispatchBuild();
 
-        // The final output is sorted based on rank
+        // The final output is sorted based first by rank and then by when
         verifyBuiltList(
                 notif(6),
                 notif(5),
@@ -204,7 +203,7 @@
         addGroupSummary(6, PACKAGE_1, GROUP_1).setRank(3);
         dispatchBuild();
 
-        // THEN the notifs are grouped together
+        // THEN the children are sorted by rank and when
         verifyBuiltList(
                 group(
                         summary(6),
@@ -503,10 +502,6 @@
         addNotif(5, PACKAGE_3);
         dispatchBuild();
 
-        for (NotificationEntry entry : mEntrySet) {
-            Log.d("pizza", "entry: " + entry.getKey() + " " + entry);
-        }
-
         // THEN both promoters are called on each child, except for children that a previous
         // promoter has already promoted
         verify(promoter1).shouldPromoteToTopLevel(mEntrySet.get(1));
@@ -840,6 +835,9 @@
                 notif(0)
         );
         assertNull(group.getParent());
+
+        // but its previous parent indicates that it was added in the previous iteration
+        assertEquals(GroupEntry.ROOT_ENTRY, group.getPreviousParent());
     }
 
     @Test(expected = IllegalStateException.class)
@@ -860,14 +858,14 @@
 
     @Test(expected = IllegalStateException.class)
     public void testOutOfOrderPrompterInvalidationThrows() {
-        // GIVEN a NotifFilter that gets invalidated during the grouping stage
+        // GIVEN a NotifPromoter that gets invalidated during the sorting stage
         NotifPromoter promoter = new IdPromoter(47);
         OnBeforeSortListener listener =
                 (list) -> promoter.invalidateList();
         mListBuilder.addPromoter(promoter);
         mListBuilder.addOnBeforeSortListener(listener);
 
-        // WHEN we try to run the pipeline and the filter is invalidated
+        // WHEN we try to run the pipeline and the promoter is invalidated
         addNotif(0, PACKAGE_1);
         dispatchBuild();
 
@@ -876,14 +874,14 @@
 
     @Test(expected = IllegalStateException.class)
     public void testOutOfOrderComparatorInvalidationThrows() {
-        // GIVEN a NotifFilter that gets invalidated during the grouping stage
+        // GIVEN a NotifComparator that gets invalidated during the finalizing stage
         NotifComparator comparator = new HypeComparator(PACKAGE_5);
         OnBeforeRenderListListener listener =
                 (list) -> comparator.invalidateList();
         mListBuilder.setComparators(Collections.singletonList(comparator));
         mListBuilder.addOnBeforeRenderListListener(listener);
 
-        // WHEN we try to run the pipeline and the filter is invalidated
+        // WHEN we try to run the pipeline and the comparator is invalidated
         addNotif(0, PACKAGE_1);
         dispatchBuild();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
index 71c2e11..ba28879 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
@@ -139,7 +139,7 @@
     @Test
     public void testInflationThrowsErrorDoesntCallUpdated() throws Exception {
         mRow.getPrivateLayout().removeAllViews();
-        mRow.getStatusBarNotification().getNotification().contentView
+        mRow.getEntry().getSbn().getNotification().contentView
                 = new RemoteViews(mContext.getPackageName(), R.layout.status_bar);
         runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
                 true /* expectingException */, mNotificationInflater);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 0b123fc..749dae5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -320,7 +320,7 @@
                 .setUserSentiment(USER_SENTIMENT_NEGATIVE)
                 .build();
         when(row.getIsNonblockable()).thenReturn(false);
-        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+        StatusBarNotification statusBarNotification = row.getEntry().getSbn();
         NotificationEntry entry = row.getEntry();
 
         mGutsManager.initializeNotificationInfo(row, notificationInfoView);
@@ -352,7 +352,7 @@
                 .setUserSentiment(USER_SENTIMENT_NEGATIVE)
                 .build();
         when(row.getIsNonblockable()).thenReturn(false);
-        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+        StatusBarNotification statusBarNotification = row.getEntry().getSbn();
         NotificationEntry entry = row.getEntry();
 
         mGutsManager.initializeNotificationInfo(row, notificationInfoView);
@@ -386,7 +386,7 @@
                 .build();
         row.getEntry().setIsHighPriority(true);
         when(row.getIsNonblockable()).thenReturn(false);
-        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+        StatusBarNotification statusBarNotification = row.getEntry().getSbn();
         NotificationEntry entry = row.getEntry();
 
         mGutsManager.initializeNotificationInfo(row, notificationInfoView);
@@ -418,7 +418,7 @@
                 .setUserSentiment(USER_SENTIMENT_NEGATIVE)
                 .build();
         when(row.getIsNonblockable()).thenReturn(false);
-        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+        StatusBarNotification statusBarNotification = row.getEntry().getSbn();
         NotificationEntry entry = row.getEntry();
 
         when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
@@ -452,7 +452,7 @@
                 .setUserSentiment(USER_SENTIMENT_NEGATIVE)
                 .build();
         when(row.getIsNonblockable()).thenReturn(false);
-        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+        StatusBarNotification statusBarNotification = row.getEntry().getSbn();
         NotificationEntry entry = row.getEntry();
 
         mGutsManager.initializeNotificationInfo(row, notificationInfoView);
@@ -530,7 +530,7 @@
 
     private NotificationMenuRowPlugin.MenuItem createTestMenuItem(ExpandableNotificationRow row) {
         NotificationMenuRowPlugin menuRow = new NotificationMenuRow(mContext);
-        menuRow.createMenu(row, row.getStatusBarNotification());
+        menuRow.createMenu(row, row.getEntry().getSbn());
 
         NotificationMenuRowPlugin.MenuItem menuItem = menuRow.getLongpressMenuItem(mContext);
         assertNotNull(menuItem);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 5b624bc..d20a37a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -448,12 +448,12 @@
                 mock(ExpandableNotificationRow.LongPressListener.class));
 
         ExpandableNotificationRow row = mock(ExpandableNotificationRow.class, RETURNS_DEEP_STUBS);
-        when(row.getStatusBarNotification().getLogMaker()).thenReturn(new LogMaker(
+        when(row.getEntry().getSbn().getLogMaker()).thenReturn(new LogMaker(
                 MetricsProto.MetricsEvent.VIEW_UNKNOWN));
 
         mStackScroller.mMenuEventListener.onMenuClicked(row, 0, 0, mock(
                 NotificationMenuRowPlugin.MenuItem.class));
-        verify(row.getStatusBarNotification()).getLogMaker();  // This writes most of the log data
+        verify(row.getEntry().getSbn()).getLogMaker();  // This writes most of the log data
         verify(mMetricsLogger).write(logMatcher(MetricsProto.MetricsEvent.ACTION_TOUCH_GEAR,
                 MetricsProto.MetricsEvent.TYPE_ACTION));
     }
@@ -463,11 +463,11 @@
     public void testOnMenuShownLogging() { ;
 
         ExpandableNotificationRow row = mock(ExpandableNotificationRow.class, RETURNS_DEEP_STUBS);
-        when(row.getStatusBarNotification().getLogMaker()).thenReturn(new LogMaker(
+        when(row.getEntry().getSbn().getLogMaker()).thenReturn(new LogMaker(
                 MetricsProto.MetricsEvent.VIEW_UNKNOWN));
 
         mStackScroller.mMenuEventListener.onMenuShown(row);
-        verify(row.getStatusBarNotification()).getLogMaker();  // This writes most of the log data
+        verify(row.getEntry().getSbn()).getLogMaker();  // This writes most of the log data
         verify(mMetricsLogger).write(logMatcher(MetricsProto.MetricsEvent.ACTION_REVEAL_GEAR,
                 MetricsProto.MetricsEvent.TYPE_ACTION));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
index a49ae35..3ad1e39 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
@@ -87,7 +87,6 @@
         ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
         entry.setRow(row);
         when(row.getEntry()).thenReturn(entry);
-        when(row.getStatusBarNotification()).thenReturn(entry.getSbn());
         when(row.isInflationFlagSet(anyInt())).thenReturn(true);
         return entry;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 24a5d93..07be0d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -141,13 +141,13 @@
 
         // Create standard notification with contentIntent
         mNotificationRow = mNotificationTestHelper.createRow();
-        StatusBarNotification sbn = mNotificationRow.getStatusBarNotification();
+        StatusBarNotification sbn = mNotificationRow.getEntry().getSbn();
         sbn.getNotification().contentIntent = mContentIntent;
         sbn.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
 
         // Create bubble notification row with contentIntent
         mBubbleNotificationRow = mNotificationTestHelper.createBubble();
-        StatusBarNotification bubbleSbn = mBubbleNotificationRow.getStatusBarNotification();
+        StatusBarNotification bubbleSbn = mBubbleNotificationRow.getEntry().getSbn();
         bubbleSbn.getNotification().contentIntent = mContentIntent;
         bubbleSbn.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
 
@@ -194,7 +194,7 @@
     public void testOnNotificationClicked_keyGuardShowing()
             throws PendingIntent.CanceledException, RemoteException {
         // Given
-        StatusBarNotification sbn = mNotificationRow.getStatusBarNotification();
+        StatusBarNotification sbn = mNotificationRow.getEntry().getSbn();
         sbn.getNotification().contentIntent = mContentIntent;
         sbn.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
 
@@ -228,7 +228,7 @@
     @Test
     public void testOnNotificationClicked_bubble_noContentIntent_noKeyGuard()
             throws RemoteException {
-        StatusBarNotification sbn = mBubbleNotificationRow.getStatusBarNotification();
+        StatusBarNotification sbn = mBubbleNotificationRow.getEntry().getSbn();
 
         // Given
         sbn.getNotification().contentIntent = null;
@@ -257,7 +257,7 @@
     @Test
     public void testOnNotificationClicked_bubble_noContentIntent_keyGuardShowing()
             throws RemoteException {
-        StatusBarNotification sbn = mBubbleNotificationRow.getStatusBarNotification();
+        StatusBarNotification sbn = mBubbleNotificationRow.getEntry().getSbn();
 
         // Given
         sbn.getNotification().contentIntent = null;
@@ -287,7 +287,7 @@
     @Test
     public void testOnNotificationClicked_bubble_withContentIntent_keyGuardShowing()
             throws RemoteException {
-        StatusBarNotification sbn = mBubbleNotificationRow.getStatusBarNotification();
+        StatusBarNotification sbn = mBubbleNotificationRow.getEntry().getSbn();
 
         // Given
         sbn.getNotification().contentIntent = mContentIntent;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
index 48ed4ba..05a4867 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
@@ -20,6 +20,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Intent;
+import android.os.Handler;
 import android.os.PowerManager;
 import android.os.PowerSaveState;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -53,7 +54,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mBatteryController = new BatteryControllerImpl(getContext(), mock(EnhancedEstimates.class),
-                mPowerManager, mBroadcastDispatcher);
+                mPowerManager, mBroadcastDispatcher, new Handler(), new Handler());
     }
 
     @Test
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4bb29f0..3dc745b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -346,7 +346,6 @@
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
 import com.android.server.appop.AppOpsService;
-import com.android.server.compat.CompatConfig;
 import com.android.server.compat.PlatformCompat;
 import com.android.server.contentcapture.ContentCaptureManagerInternal;
 import com.android.server.firewall.IntentFirewall;
@@ -5032,8 +5031,9 @@
             bindApplicationTimeMillis = SystemClock.elapsedRealtime();
             mAtmInternal.preBindApplication(app.getWindowProcessController());
             final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
-            long[] disabledCompatChanges = CompatConfig.get().getDisabledChanges(app.info);
+            long[] disabledCompatChanges = {};
             if (mPlatformCompat != null) {
+                disabledCompatChanges = mPlatformCompat.getDisabledChanges(app.info);
                 mPlatformCompat.resetReporting(app.info);
             }
             if (app.isolatedEntryPoint != null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 1f56176..908ec6b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -37,11 +37,13 @@
 import android.app.IUidObserver;
 import android.app.KeyguardManager;
 import android.app.ProfilerInfo;
+import android.app.UserSwitchObserver;
 import android.app.WaitResult;
 import android.app.usage.AppStandbyInfo;
 import android.app.usage.ConfigurationStats;
 import android.app.usage.IUsageStatsManager;
 import android.app.usage.UsageStatsManager;
+import android.compat.Compatibility;
 import android.content.ComponentCallbacks2;
 import android.content.ComponentName;
 import android.content.Context;
@@ -80,15 +82,17 @@
 import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.DebugUtils;
 import android.util.DisplayMetrics;
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
 
+import com.android.internal.compat.CompatibilityChangeConfig;
 import com.android.internal.util.HexDump;
 import com.android.internal.util.MemInfoReader;
 import com.android.internal.util.Preconditions;
-import com.android.server.compat.CompatConfig;
+import com.android.server.compat.PlatformCompat;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -1729,6 +1733,30 @@
         return 0;
     }
 
+    private void switchUserAndWaitForComplete(int userId) throws RemoteException {
+        // Register switch observer.
+        final CountDownLatch switchLatch = new CountDownLatch(1);
+        mInterface.registerUserSwitchObserver(
+                new UserSwitchObserver() {
+                    @Override
+                    public void onUserSwitchComplete(int newUserId) {
+                        if (userId == newUserId) {
+                            switchLatch.countDown();
+                        }
+                    }
+                }, ActivityManagerShellCommand.class.getName());
+
+        // Switch.
+        mInterface.switchUser(userId);
+
+        // Wait.
+        try {
+            switchLatch.await(USER_OPERATION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            getErrPrintWriter().println("Thread interrupted unexpectedly.");
+        }
+    }
+
     int runSwitchUser(PrintWriter pw) throws RemoteException {
         UserManager userManager = mInternal.mContext.getSystemService(UserManager.class);
         final int userSwitchable = userManager.getUserSwitchability();
@@ -1736,8 +1764,23 @@
             getErrPrintWriter().println("Error: " + userSwitchable);
             return -1;
         }
-        String user = getNextArgRequired();
-        mInterface.switchUser(Integer.parseInt(user));
+        boolean wait = false;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            if ("-w".equals(opt)) {
+                wait = true;
+            } else {
+                getErrPrintWriter().println("Error: unknown option: " + opt);
+                return -1;
+            }
+        }
+
+        int userId = Integer.parseInt(getNextArgRequired());
+        if (wait) {
+            switchUserAndWaitForComplete(userId);
+        } else {
+            mInterface.switchUser(userId);
+        }
         return 0;
     }
 
@@ -2862,56 +2905,49 @@
         return 0;
     }
 
-    private void killPackage(String packageName, PrintWriter pw) throws RemoteException {
-        int uid = mPm.getPackageUid(packageName, 0, mUserId);
-        if (uid < 0) {
-            // uid is negative if the package wasn't found.
-            pw.println("Didn't find package " + packageName + " on device.");
-        } else {
-            pw.println("Killing package " + packageName + " (UID " + uid + ").");
-            final long origId = Binder.clearCallingIdentity();
-            mInterface.killUid(UserHandle.getAppId(uid),
-                    UserHandle.USER_ALL, "killPackage");
-            Binder.restoreCallingIdentity(origId);
-        }
-    }
-
     private int runCompat(PrintWriter pw) throws RemoteException {
-        final CompatConfig config = CompatConfig.get();
+        final PlatformCompat platformCompat = (PlatformCompat)
+                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
         String toggleValue = getNextArgRequired();
         long changeId;
         String changeIdString = getNextArgRequired();
         try {
             changeId = Long.parseLong(changeIdString);
         } catch (NumberFormatException e) {
-            changeId = config.lookupChangeId(changeIdString);
+            changeId = platformCompat.lookupChangeId(changeIdString);
         }
         if (changeId == -1) {
             pw.println("Unknown or invalid change: '" + changeIdString + "'.");
+            return -1;
         }
         String packageName = getNextArgRequired();
+        if (!platformCompat.isKnownChangeId(changeId)) {
+            pw.println("Warning! Change " + changeId + " is not known yet. Enabling/disabling it"
+                    + " could have no effect.");
+        }
+        ArraySet<Long> enabled = new ArraySet<>();
+        ArraySet<Long> disabled = new ArraySet<>();
         switch (toggleValue) {
             case "enable":
-                if (!config.addOverride(changeId, packageName, true)) {
-                    pw.println("Warning! Change " + changeId + " is not known yet. Enabling it"
-                            + " could have no effect.");
-                }
+                enabled.add(changeId);
                 pw.println("Enabled change " + changeId + " for " + packageName + ".");
-                killPackage(packageName, pw);
+                CompatibilityChangeConfig overrides =
+                        new CompatibilityChangeConfig(
+                                new Compatibility.ChangeConfig(enabled, disabled));
+                platformCompat.setOverrides(overrides, packageName);
                 return 0;
             case "disable":
-                if (!config.addOverride(changeId, packageName, false)) {
-                    pw.println("Warning! Change " + changeId + " is not known yet. Disabling it"
-                            + " could have no effect.");
-                }
+                disabled.add(changeId);
                 pw.println("Disabled change " + changeId + " for " + packageName + ".");
-                killPackage(packageName, pw);
+                overrides =
+                        new CompatibilityChangeConfig(
+                                new Compatibility.ChangeConfig(enabled, disabled));
+                platformCompat.setOverrides(overrides, packageName);
                 return 0;
             case "reset":
-                if (config.removeOverride(changeId, packageName)) {
+                if (platformCompat.clearOverride(changeId, packageName)) {
                     pw.println("Reset change " + changeId + " for " + packageName
                             + " to default value.");
-                    killPackage(packageName, pw);
                 } else {
                     pw.println("No override exists for changeId " + changeId + ".");
                 }
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index d6ec22b..490cce3 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -43,13 +43,14 @@
 import java.util.Set;
 
 import javax.xml.datatype.DatatypeConfigurationException;
+
 /**
  * This class maintains state relating to platform compatibility changes.
  *
  * <p>It stores the default configuration for each change, and any per-package overrides that have
  * been configured.
  */
-public final class CompatConfig {
+final class CompatConfig {
 
     private static final String TAG = "CompatConfig";
 
@@ -61,13 +62,13 @@
     private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>();
 
     @VisibleForTesting
-    public CompatConfig() {
+    CompatConfig() {
     }
 
     /**
      * @return The static instance of this class to be used within the system server.
      */
-    public static CompatConfig get() {
+    static CompatConfig get() {
         return sInstance;
     }
 
@@ -77,7 +78,7 @@
      *
      * @param change The change to add. Any change with the same ID will be overwritten.
      */
-    public void addChange(CompatChange change) {
+    void addChange(CompatChange change) {
         synchronized (mChanges) {
             mChanges.put(change.getId(), change);
         }
@@ -89,10 +90,10 @@
      *
      * @param app The app in question
      * @return A sorted long array of change IDs. We use a primitive array to minimize memory
-     *      footprint: Every app process will store this array statically so we aim to reduce
-     *      overhead as much as possible.
+     * footprint: Every app process will store this array statically so we aim to reduce
+     * overhead as much as possible.
      */
-    public long[] getDisabledChanges(ApplicationInfo app) {
+    long[] getDisabledChanges(ApplicationInfo app) {
         LongArray disabled = new LongArray();
         synchronized (mChanges) {
             for (int i = 0; i < mChanges.size(); ++i) {
@@ -113,7 +114,7 @@
      * @param name Name of the change to look up
      * @return The change ID, or {@code -1} if no change with that name exists.
      */
-    public long lookupChangeId(String name) {
+    long lookupChangeId(String name) {
         synchronized (mChanges) {
             for (int i = 0; i < mChanges.size(); ++i) {
                 if (TextUtils.equals(mChanges.valueAt(i).getName(), name)) {
@@ -128,11 +129,11 @@
      * Find if a given change is enabled for a given application.
      *
      * @param changeId The ID of the change in question
-     * @param app App to check for
+     * @param app      App to check for
      * @return {@code true} if the change is enabled for this app. Also returns {@code true} if the
-     *      change ID is not known, as unknown changes are enabled by default.
+     * change ID is not known, as unknown changes are enabled by default.
      */
-    public boolean isChangeEnabled(long changeId, ApplicationInfo app) {
+    boolean isChangeEnabled(long changeId, ApplicationInfo app) {
         synchronized (mChanges) {
             CompatChange c = mChanges.get(changeId);
             if (c == null) {
@@ -150,14 +151,15 @@
      *
      * <p>Note, package overrides are not persistent and will be lost on system or runtime restart.
      *
-     * @param changeId The ID of the change to be overridden. Note, this call will succeed even if
-     *                 this change is not known; it will only have any effect if any code in the
-     *                 platform is gated on the ID given.
+     * @param changeId    The ID of the change to be overridden. Note, this call will succeed even
+     *                    if
+     *                    this change is not known; it will only have any effect if any code in the
+     *                    platform is gated on the ID given.
      * @param packageName The app package name to override the change for.
-     * @param enabled If the change should be enabled or disabled.
+     * @param enabled     If the change should be enabled or disabled.
      * @return {@code true} if the change existed before adding the override.
      */
-    public boolean addOverride(long changeId, String packageName, boolean enabled) {
+    boolean addOverride(long changeId, String packageName, boolean enabled) {
         boolean alreadyKnown = true;
         synchronized (mChanges) {
             CompatChange c = mChanges.get(changeId);
@@ -172,15 +174,27 @@
     }
 
     /**
+     * Check whether the change is known to the compat config.
+     *
+     * @return {@code true} if the change is known.
+     */
+    boolean isKnownChangeId(long changeId) {
+        synchronized (mChanges) {
+            CompatChange c = mChanges.get(changeId);
+            return c != null;
+        }
+    }
+
+    /**
      * Removes an override previously added via {@link #addOverride(long, String, boolean)}. This
      * restores the default behaviour for the given change and app, once any app processes have been
      * restarted.
      *
-     * @param changeId The ID of the change that was overridden.
+     * @param changeId    The ID of the change that was overridden.
      * @param packageName The app package name that was overridden.
      * @return {@code true} if an override existed;
      */
-    public boolean removeOverride(long changeId, String packageName) {
+    boolean removeOverride(long changeId, String packageName) {
         boolean overrideExists = false;
         synchronized (mChanges) {
             CompatChange c = mChanges.get(changeId);
@@ -191,22 +205,22 @@
         }
         return overrideExists;
     }
+
     /**
      * Overrides the enabled state for a given change and app. This method is intended to be used
      * *only* for debugging purposes.
      *
      * <p>Note, package overrides are not persistent and will be lost on system or runtime restart.
      *
-     * @param overrides list of overrides to default changes config.
+     * @param overrides   list of overrides to default changes config.
      * @param packageName app for which the overrides will be applied.
      */
-    public void addOverrides(
-            CompatibilityChangeConfig overrides, String packageName) {
+    void addOverrides(CompatibilityChangeConfig overrides, String packageName) {
         synchronized (mChanges) {
-            for (Long changeId: overrides.enabledChanges()) {
+            for (Long changeId : overrides.enabledChanges()) {
                 addOverride(changeId, packageName, true);
             }
-            for (Long changeId: overrides.disabledChanges()) {
+            for (Long changeId : overrides.disabledChanges()) {
                 addOverride(changeId, packageName, false);
             }
         }
@@ -221,7 +235,7 @@
      *
      * @param packageName The package for which the overrides should be purged.
      */
-    public void removePackageOverrides(String packageName) {
+    void removePackageOverrides(String packageName) {
         synchronized (mChanges) {
             for (int i = 0; i < mChanges.size(); ++i) {
                 mChanges.valueAt(i).removePackageOverride(packageName);
@@ -230,11 +244,11 @@
     }
 
     /**
-    * Dumps the current list of compatibility config information.
-    *
-    * @param pw The {@link PrintWriter} instance to which the information will be dumped.
-    */
-    public void dumpConfig(PrintWriter pw) {
+     * Dumps the current list of compatibility config information.
+     *
+     * @param pw The {@link PrintWriter} instance to which the information will be dumped.
+     */
+    void dumpConfig(PrintWriter pw) {
         synchronized (mChanges) {
             if (mChanges.size() == 0) {
                 pw.println("No compat overrides.");
@@ -252,10 +266,10 @@
      *
      * @param applicationInfo the {@link ApplicationInfo} for which the info should be dumped.
      * @return A {@link CompatibilityChangeConfig} which contains the compat config info for the
-     *         given app.
+     * given app.
      */
 
-    public CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) {
+    CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) {
         Set<Long> enabled = new HashSet<>();
         Set<Long> disabled = new HashSet<>();
         synchronized (mChanges) {
@@ -276,15 +290,15 @@
      *
      * @return An array of {@link CompatibilityChangeInfo} with the current changes.
      */
-    public CompatibilityChangeInfo[] dumpChanges() {
+    CompatibilityChangeInfo[] dumpChanges() {
         synchronized (mChanges) {
             CompatibilityChangeInfo[] changeInfos = new CompatibilityChangeInfo[mChanges.size()];
             for (int i = 0; i < mChanges.size(); ++i) {
                 CompatChange change = mChanges.valueAt(i);
                 changeInfos[i] = new CompatibilityChangeInfo(change.getId(),
-                                                      change.getName(),
-                                                      change.getEnableAfterTargetSdk(),
-                                                      change.getDisabled());
+                        change.getName(),
+                        change.getEnableAfterTargetSdk(),
+                        change.getDisabled());
             }
             return changeInfos;
         }
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 75e2d22..709f3f8 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -16,9 +16,13 @@
 
 package com.android.server.compat;
 
+import android.app.ActivityManager;
+import android.app.IActivityManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Slog;
 import android.util.StatsLog;
@@ -106,12 +110,26 @@
     @Override
     public void setOverrides(CompatibilityChangeConfig overrides, String packageName) {
         CompatConfig.get().addOverrides(overrides, packageName);
+        killPackage(packageName);
+    }
+
+    @Override
+    public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) {
+        CompatConfig.get().addOverrides(overrides, packageName);
     }
 
     @Override
     public void clearOverrides(String packageName) {
         CompatConfig config = CompatConfig.get();
         config.removePackageOverrides(packageName);
+        killPackage(packageName);
+    }
+
+    @Override
+    public boolean clearOverride(long changeId, String packageName) {
+        boolean existed = CompatConfig.get().removeOverride(changeId, packageName);
+        killPackage(packageName);
+        return existed;
     }
 
     @Override
@@ -124,6 +142,39 @@
         return CompatConfig.get().dumpChanges();
     }
 
+    /**
+     * Check whether the change is known to the compat config.
+     * @param changeId
+     * @return {@code true} if the change is known.
+     */
+    public boolean isKnownChangeId(long changeId) {
+        return CompatConfig.get().isKnownChangeId(changeId);
+
+    }
+
+    /**
+     * Retrieves the set of disabled changes for a given app. Any change ID not in the returned
+     * array is by default enabled for the app.
+     *
+     * @param appInfo The app in question
+     * @return A sorted long array of change IDs. We use a primitive array to minimize memory
+     *      footprint: Every app process will store this array statically so we aim to reduce
+     *      overhead as much as possible.
+     */
+    public long[] getDisabledChanges(ApplicationInfo appInfo) {
+        return CompatConfig.get().getDisabledChanges(appInfo);
+    }
+
+    /**
+     * Look up a change ID by name.
+     *
+     * @param name Name of the change to look up
+     * @return The change ID, or {@code -1} if no change with that name exists.
+     */
+    public long lookupChangeId(String name) {
+        return CompatConfig.get().lookupChangeId(name);
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
@@ -151,4 +202,34 @@
     private void reportChange(long changeId, int uid, int state) {
         mChangeReporter.reportChange(uid, changeId, state);
     }
+
+    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);
+            return;
+        }
+
+        Slog.d(TAG, "Killing package " + packageName + " (UID " + uid + ").");
+        killUid(UserHandle.getAppId(uid),
+                UserHandle.USER_ALL, "PlatformCompat overrides");
+    }
+
+    private void killUid(int appId, int userId, String reason) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            IActivityManager am = ActivityManager.getService();
+            if (am != null) {
+                try {
+                    am.killUid(appId, userId, reason);
+                } catch (RemoteException e) {
+                    /* ignore - same process */
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index b3804c4..acedc36 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -286,8 +286,8 @@
 
     private void startStateMachineUpdaters(Handler handler) {
         mCarrierConfigChange.startListening();
-        TelephonyManager.from(mContext).listen(mPhoneStateListener,
-                PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
+        mContext.getSystemService(TelephonyManager.class).listen(
+                mPhoneStateListener, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(UsbManager.ACTION_USB_STATE);
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 126beef..eea1980 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -34,6 +34,7 @@
 import android.hardware.SensorManager;
 import android.hardware.display.AmbientBrightnessDayStats;
 import android.hardware.display.BrightnessChangeEvent;
+import android.hardware.display.BrightnessConfiguration;
 import android.hardware.display.ColorDisplayManager;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerInternal;
@@ -125,6 +126,7 @@
     private static final int MSG_BRIGHTNESS_CHANGED = 1;
     private static final int MSG_STOP_SENSOR_LISTENER = 2;
     private static final int MSG_START_SENSOR_LISTENER = 3;
+    private static final int MSG_BRIGHTNESS_CONFIG_CHANGED = 4;
 
     private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
 
@@ -158,6 +160,7 @@
     private boolean mColorSamplingEnabled;
     private int mNoFramesToSample;
     private float mFrameRate;
+    private BrightnessConfiguration mBrightnessConfiguration;
     // End of block of members that should only be accessed on the mBgHandler thread.
 
     private @UserIdInt int mCurrentUserId = UserHandle.USER_NULL;
@@ -202,6 +205,14 @@
         mBgHandler.obtainMessage(MSG_BACKGROUND_START, (Float) initialBrightness).sendToTarget();
     }
 
+    /**
+     * Update tracker with new brightness configuration.
+     */
+    public void setBrightnessConfiguration(BrightnessConfiguration brightnessConfiguration) {
+        mBgHandler.obtainMessage(MSG_BRIGHTNESS_CONFIG_CHANGED,
+                brightnessConfiguration).sendToTarget();
+    }
+
     private void backgroundStart(float initialBrightness) {
         readEvents();
         readAmbientBrightnessStats();
@@ -759,7 +770,9 @@
     private void enableColorSampling() {
         if (!mInjector.isBrightnessModeAutomatic(mContentResolver)
                 || !mInjector.isInteractive(mContext)
-                || mColorSamplingEnabled) {
+                || mColorSamplingEnabled
+                || mBrightnessConfiguration == null
+                || !mBrightnessConfiguration.shouldCollectColorSamples()) {
             return;
         }
 
@@ -977,6 +990,18 @@
                     stopSensorListener();
                     disableColorSampling();
                     break;
+                case MSG_BRIGHTNESS_CONFIG_CHANGED:
+                    mBrightnessConfiguration = (BrightnessConfiguration) msg.obj;
+                    boolean shouldCollectColorSamples =
+                            mBrightnessConfiguration != null
+                                    && mBrightnessConfiguration.shouldCollectColorSamples();
+                    if (shouldCollectColorSamples && !mColorSamplingEnabled) {
+                        enableColorSampling();
+                    } else if (!shouldCollectColorSamples && mColorSamplingEnabled) {
+                        disableColorSampling();
+                    }
+                    break;
+
             }
         }
     }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 5804fc8..e42545e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -931,6 +931,10 @@
                     autoBrightnessAdjustmentChanged, mPowerRequest.policy);
         }
 
+        if (mBrightnessTracker != null) {
+            mBrightnessTracker.setBrightnessConfiguration(mBrightnessConfiguration);
+        }
+
         // Apply auto-brightness.
         boolean slowChange = false;
         if (brightness < 0) {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 8d2fc17..637bcae 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -301,6 +301,7 @@
 
     // Timeout when holding wakelocks for downloading PSDS data.
     private static final long DOWNLOAD_PSDS_DATA_TIMEOUT_MS = 60 * 1000;
+    private static final long WAKELOCK_TIMEOUT_MILLIS = 30 * 1000;
 
     private final ExponentialBackOff mPsdsBackOff = new ExponentialBackOff(RETRY_INTERVAL,
             MAX_RETRY_INTERVAL);
@@ -901,13 +902,8 @@
                 if (mDownloadPsdsWakeLock.isHeld()) {
                     // This wakelock may have time-out, if a timeout was specified.
                     // Catch (and ignore) any timeout exceptions.
-                    try {
-                        mDownloadPsdsWakeLock.release();
-                        if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadPsdsData()");
-                    } catch (Exception e) {
-                        Log.i(TAG, "Wakelock timeout & release race exception in "
-                                + "handleDownloadPsdsData()", e);
-                    }
+                    mDownloadPsdsWakeLock.release();
+                    if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadPsdsData()");
                 } else {
                     Log.e(TAG, "WakeLock expired before release in "
                             + "handleDownloadPsdsData()");
@@ -2009,7 +2005,7 @@
         // hold a wake lock until this message is delivered
         // note that this assumes the message will not be removed from the queue before
         // it is handled (otherwise the wake lock would be leaked).
-        mWakeLock.acquire();
+        mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
         if (DEBUG) {
             Log.d(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg
                     + ", " + obj + ")");
diff --git a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
index 2e72fbd..93227bd 100644
--- a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
+++ b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
@@ -321,7 +321,11 @@
 
     private void handleUpdateNetworkState(Network network, boolean isConnected,
             NetworkCapabilities capabilities) {
-        boolean networkAvailable = isConnected && TelephonyManager.getDefault().getDataEnabled();
+        boolean networkAvailable = false;
+        TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
+        if (telephonyManager != null) {
+            networkAvailable = isConnected && telephonyManager.getDataEnabled();
+        }
         NetworkAttributes networkAttributes = updateTrackedNetworksState(isConnected, network,
                 capabilities);
         String apn = networkAttributes.mApn;
diff --git a/services/core/java/com/android/server/location/NtpTimeHelper.java b/services/core/java/com/android/server/location/NtpTimeHelper.java
index 296b500..67841ac 100644
--- a/services/core/java/com/android/server/location/NtpTimeHelper.java
+++ b/services/core/java/com/android/server/location/NtpTimeHelper.java
@@ -181,11 +181,7 @@
                 mHandler.postDelayed(this::retrieveAndInjectNtpTime, delay);
             }
         }
-        try {
-            // release wake lock held by task
-            mWakeLock.release();
-        } catch (Exception e) {
-            // This happens when the WakeLock is already released.
-        }
+        // release wake lock held by task
+        mWakeLock.release();
     }
 }
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 41806ca..08c9426 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -337,7 +337,7 @@
                 powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
 
         NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager,
-                wakeLock, getDefaultClock(), TelephonyManager.getDefault(),
+                wakeLock, getDefaultClock(), context.getSystemService(TelephonyManager.class),
                 new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(),
                 new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir());
         service.registerLocalService();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 5b39fb6..ec53157 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7724,7 +7724,7 @@
     }
 
     private void listenForCallState() {
-        TelephonyManager.from(getContext()).listen(new PhoneStateListener() {
+        getContext().getSystemService(TelephonyManager.class).listen(new PhoneStateListener() {
             @Override
             public void onCallStateChanged(int state, String incomingNumber) {
                 if (mCallState == state) return;
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index bb5b04a..ec11a97 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -29,27 +29,24 @@
 import android.content.pm.PackageParser;
 import android.content.pm.ProviderInfo;
 import android.net.Uri;
-import android.os.Build;
 import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.Trace;
-import android.permission.IPermissionManager;
+import android.os.UserHandle;
 import android.provider.DeviceConfig;
+import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseSetArray;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
 import com.android.server.FgThread;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
@@ -60,7 +57,7 @@
 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
 public class AppsFilter {
 
-    private static final String TAG = PackageManagerService.TAG;
+    private static final String TAG = "AppsFilter";
 
     // Logs all filtering instead of enforcing
     private static final boolean DEBUG_ALLOW_ALL = false;
@@ -69,52 +66,46 @@
     private static final boolean DEBUG_LOGGING = false | DEBUG_ALLOW_ALL;
 
     /**
-     * This contains a list of packages that are implicitly queryable because another app explicitly
+     * This contains a list of app UIDs that are implicitly queryable because another app explicitly
      * interacted with it. For example, if application A starts a service in application B,
      * application B is implicitly allowed to query for application A; regardless of any manifest
      * entries.
      */
-    private final SparseArray<HashMap<String, Set<String>>> mImplicitlyQueryable =
-            new SparseArray<>();
+    private final SparseSetArray<Integer> mImplicitlyQueryable = new SparseSetArray<>();
 
     /**
-     * A mapping from the set of packages that query other packages via package name to the
+     * A mapping from the set of App IDs that query other App IDs via package name to the
      * list of packages that they can see.
      */
-    private final HashMap<String, Set<String>> mQueriesViaPackage = new HashMap<>();
+    private final SparseSetArray<Integer> mQueriesViaPackage = new SparseSetArray<>();
 
     /**
-     * A mapping from the set of packages that query others via intent to the list
+     * A mapping from the set of App IDs that query others via intent to the list
      * of packages that the intents resolve to.
      */
-    private final HashMap<String, Set<String>> mQueriesViaIntent = new HashMap<>();
+    private final SparseSetArray<Integer> mQueriesViaIntent = new SparseSetArray<>();
 
     /**
-     * A set of packages that are always queryable by any package, regardless of their manifest
+     * A set of App IDs that are always queryable by any package, regardless of their manifest
      * content.
      */
-    private final HashSet<String> mForceQueryable;
+    private final ArraySet<Integer> mForceQueryable = new ArraySet<>();
+
     /**
-     * A set of packages that are always queryable by any package, regardless of their manifest
-     * content.
+     * The set of package names provided by the device that should be force queryable regardless of
+     * their manifest contents.
      */
-    private final Set<String> mForceQueryableByDevice;
+    private final String[] mForceQueryableByDevicePackageNames;
 
     /** True if all system apps should be made queryable by default. */
     private final boolean mSystemAppsQueryable;
 
-    private final IPermissionManager mPermissionManager;
-
     private final FeatureConfig mFeatureConfig;
 
-    AppsFilter(FeatureConfig featureConfig, IPermissionManager permissionManager,
-            String[] forceQueryableWhitelist, boolean systemAppsQueryable) {
+    AppsFilter(FeatureConfig featureConfig, String[] forceQueryableWhitelist,
+            boolean systemAppsQueryable) {
         mFeatureConfig = featureConfig;
-        final HashSet<String> forceQueryableByDeviceSet = new HashSet<>();
-        Collections.addAll(forceQueryableByDeviceSet, forceQueryableWhitelist);
-        this.mForceQueryableByDevice = Collections.unmodifiableSet(forceQueryableByDeviceSet);
-        this.mForceQueryable = new HashSet<>();
-        mPermissionManager = permissionManager;
+        mForceQueryableByDevicePackageNames = forceQueryableWhitelist;
         mSystemAppsQueryable = systemAppsQueryable;
     }
 
@@ -127,7 +118,6 @@
 
         /** @return true if the feature is enabled for the given package. */
         boolean packageIsEnabled(PackageParser.Package pkg);
-
     }
 
     private static class FeatureConfigImpl implements FeatureConfig {
@@ -174,7 +164,6 @@
         }
     }
 
-
     public static AppsFilter create(PackageManagerService.Injector injector) {
         final boolean forceSystemAppsQueryable =
                 injector.getContext().getResources()
@@ -192,15 +181,12 @@
                 forcedQueryablePackageNames[i] = forcedQueryablePackageNames[i].intern();
             }
         }
-        IPermissionManager permissionmgr =
-                (IPermissionManager) ServiceManager.getService("permissionmgr");
-
-        return new AppsFilter(featureConfig, permissionmgr, forcedQueryablePackageNames,
+        return new AppsFilter(featureConfig, forcedQueryablePackageNames,
                 forceSystemAppsQueryable);
     }
 
     /** Returns true if the querying package may query for the potential target package */
-    private static boolean canQuery(PackageParser.Package querying,
+    private static boolean canQueryViaIntent(PackageParser.Package querying,
             PackageParser.Package potentialTarget) {
         if (querying.mQueriesIntents == null) {
             return false;
@@ -274,22 +260,14 @@
      * Grants access based on an interaction between a calling and target package, granting
      * visibility of the caller from the target.
      *
-     * @param callingPackage the package initiating the interaction
-     * @param targetPackage  the package being interacted with and thus gaining visibility of the
-     *                       initiating package.
-     * @param userId         the user in which this interaction was taking place
+     * @param callingUid the uid initiating the interaction
+     * @param targetUid  the uid being interacted with and thus gaining visibility of the
+     *                   initiating uid.
      */
-    public void grantImplicitAccess(
-            String callingPackage, String targetPackage, int userId) {
-        HashMap<String, Set<String>> currentUser = mImplicitlyQueryable.get(userId);
-        if (currentUser == null) {
-            currentUser = new HashMap<>();
-            mImplicitlyQueryable.put(userId, currentUser);
+    public void grantImplicitAccess(int callingUid, int targetUid) {
+        if (mImplicitlyQueryable.add(targetUid, callingUid) && DEBUG_LOGGING) {
+            Slog.wtf(TAG, "implicit access granted: " + callingUid + " -> " + targetUid);
         }
-        if (!currentUser.containsKey(targetPackage)) {
-            currentUser.put(targetPackage, new HashSet<>());
-        }
-        currentUser.get(targetPackage).add(callingPackage);
     }
 
     public void onSystemReady() {
@@ -299,50 +277,57 @@
     /**
      * Adds a package that should be considered when filtering visibility between apps.
      *
-     * @param newPkg   the new package being added
-     * @param existing all other packages currently on the device.
+     * @param newPkgSetting    the new setting being added
+     * @param existingSettings all other settings currently on the device.
      */
-    public void addPackage(PackageParser.Package newPkg,
-            Map<String, PackageParser.Package> existing) {
+    public void addPackage(PackageSetting newPkgSetting,
+            ArrayMap<String, PackageSetting> existingSettings) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
         try {
-            // let's re-evaluate the ability of already added packages to see this new package
-            if (newPkg.mForceQueryable
-                    || (mSystemAppsQueryable && (newPkg.isSystem()
-                    || newPkg.isUpdatedSystemApp()))) {
-                mForceQueryable.add(newPkg.packageName);
-            } else {
-                for (String packageName : mQueriesViaIntent.keySet()) {
-                    if (packageName == newPkg.packageName) {
-                        continue;
+            final PackageParser.Package newPkg = newPkgSetting.pkg;
+            if (newPkg == null) {
+                // nothing to add
+                return;
+            }
+
+            final boolean newIsForceQueryable =
+                    mForceQueryable.contains(newPkgSetting.appId)
+                            /* shared user that is already force queryable */
+                            || newPkg.mForceQueryable
+                            || (newPkgSetting.isSystem() && (mSystemAppsQueryable
+                            || ArrayUtils.contains(mForceQueryableByDevicePackageNames,
+                            newPkg.packageName)));
+            if (newIsForceQueryable) {
+                mForceQueryable.add(newPkgSetting.appId);
+            }
+
+            for (int i = existingSettings.size() - 1; i >= 0; i--) {
+                final PackageSetting existingSetting = existingSettings.valueAt(i);
+                if (existingSetting.appId == newPkgSetting.appId || existingSetting.pkg == null) {
+                    continue;
+                }
+                final PackageParser.Package existingPkg = existingSetting.pkg;
+                // let's evaluate the ability of already added packages to see this new package
+                if (!newIsForceQueryable) {
+                    if (canQueryViaIntent(existingPkg, newPkg)) {
+                        mQueriesViaIntent.add(existingSetting.appId, newPkgSetting.appId);
                     }
-                    final PackageParser.Package existingPackage = existing.get(packageName);
-                    if (canQuery(existingPackage, newPkg)) {
-                        mQueriesViaIntent.get(packageName).add(newPkg.packageName);
+                    if (existingPkg.mQueriesPackages != null
+                            && existingPkg.mQueriesPackages.contains(newPkg.packageName)) {
+                        mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId);
+                    }
+                }
+                // now we'll evaluate our new package's ability to see existing packages
+                if (!mForceQueryable.contains(existingSetting.appId)) {
+                    if (canQueryViaIntent(newPkg, existingPkg)) {
+                        mQueriesViaIntent.add(newPkgSetting.appId, existingSetting.appId);
+                    }
+                    if (newPkg.mQueriesPackages != null
+                            && newPkg.mQueriesPackages.contains(existingPkg.packageName)) {
+                        mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
                     }
                 }
             }
-            // if the new package declares them, let's evaluate its ability to see existing packages
-            mQueriesViaIntent.put(newPkg.packageName, new HashSet<>());
-            for (PackageParser.Package existingPackage : existing.values()) {
-                if (existingPackage.packageName == newPkg.packageName) {
-                    continue;
-                }
-                if (existingPackage.mForceQueryable
-                        || (mSystemAppsQueryable
-                        && (newPkg.isSystem() || newPkg.isUpdatedSystemApp()))) {
-                    continue;
-                }
-                if (canQuery(newPkg, existingPackage)) {
-                    mQueriesViaIntent.get(newPkg.packageName).add(existingPackage.packageName);
-                }
-            }
-            final HashSet<String> queriesPackages = new HashSet<>(
-                    newPkg.mQueriesPackages == null ? 0 : newPkg.mQueriesPackages.size());
-            if (newPkg.mQueriesPackages != null) {
-                queriesPackages.addAll(newPkg.mQueriesPackages);
-            }
-            mQueriesViaPackage.put(newPkg.packageName, queriesPackages);
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
@@ -351,24 +336,41 @@
     /**
      * Removes a package for consideration when filtering visibility between apps.
      *
-     * @param packageName the name of the package being removed.
+     * @param setting  the setting of the package being removed.
+     * @param allUsers array of all current users on device.
      */
-    public void removePackage(String packageName) {
-        mForceQueryable.remove(packageName);
+    public void removePackage(PackageSetting setting, int[] allUsers,
+            ArrayMap<String, PackageSetting> existingSettings) {
+        mForceQueryable.remove(setting.appId);
 
-        for (int i = 0; i < mImplicitlyQueryable.size(); i++) {
-            mImplicitlyQueryable.valueAt(i).remove(packageName);
-            for (Set<String> initiators : mImplicitlyQueryable.valueAt(i).values()) {
-                initiators.remove(packageName);
+        for (int u = 0; u < allUsers.length; u++) {
+            final int userId = allUsers[u];
+            final int removingUid = UserHandle.getUid(userId, setting.appId);
+            mImplicitlyQueryable.remove(removingUid);
+            for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) {
+                mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i), removingUid);
             }
         }
 
-        mQueriesViaIntent.remove(packageName);
-        for (Set<String> declarators : mQueriesViaIntent.values()) {
-            declarators.remove(packageName);
+        mQueriesViaIntent.remove(setting.appId);
+        for (int i = mQueriesViaIntent.size() - 1; i >= 0; i--) {
+            mQueriesViaIntent.remove(mQueriesViaIntent.keyAt(i), setting.appId);
+        }
+        mQueriesViaPackage.remove(setting.appId);
+        for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) {
+            mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), setting.appId);
         }
 
-        mQueriesViaPackage.remove(packageName);
+        // re-add other shared user members to re-establish visibility between them and other
+        // packages
+        if (setting.sharedUser != null) {
+            for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) {
+                if (setting.sharedUser.packages.valueAt(i) == setting) {
+                    continue;
+                }
+                addPackage(setting.sharedUser.packages.valueAt(i), existingSettings);
+            }
+        }
     }
 
     /**
@@ -385,6 +387,25 @@
             PackageSetting targetPkgSetting, int userId) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication");
         try {
+            if (!shouldFilterApplicationInternal(callingUid, callingSetting,
+                    targetPkgSetting,
+                    userId)) {
+                return false;
+            }
+            if (DEBUG_LOGGING) {
+                log(callingSetting, targetPkgSetting,
+                        DEBUG_ALLOW_ALL ? "ALLOWED" : "BLOCKED", new RuntimeException());
+            }
+            return !DEBUG_ALLOW_ALL;
+        } finally {
+            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+        }
+    }
+
+    private boolean shouldFilterApplicationInternal(int callingUid,
+            SettingBase callingSetting, PackageSetting targetPkgSetting, int userId) {
+        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal");
+        try {
             final boolean featureEnabled = mFeatureConfig.isGloballyEnabled();
             if (!featureEnabled) {
                 if (DEBUG_LOGGING) {
@@ -402,85 +423,37 @@
                 Slog.wtf(TAG, "No setting found for non system uid " + callingUid);
                 return true;
             }
-            PackageSetting callingPkgSetting = null;
+            final PackageSetting callingPkgSetting;
+            final ArraySet<PackageSetting> callingSharedPkgSettings;
             if (callingSetting instanceof PackageSetting) {
                 callingPkgSetting = (PackageSetting) callingSetting;
-                if (!shouldFilterApplicationInternal(callingPkgSetting, targetPkgSetting,
-                        userId)) {
+                callingSharedPkgSettings = null;
+            } else {
+                callingPkgSetting = null;
+                callingSharedPkgSettings = ((SharedUserSetting) callingSetting).packages;
+            }
+
+            if (callingPkgSetting != null) {
+                if (!mFeatureConfig.packageIsEnabled(callingPkgSetting.pkg)) {
+                    if (DEBUG_LOGGING) {
+                        log(callingSetting, targetPkgSetting, "DISABLED");
+                    }
                     return false;
                 }
-            } else if (callingSetting instanceof SharedUserSetting) {
-                final ArraySet<PackageSetting> packageSettings =
-                        ((SharedUserSetting) callingSetting).packages;
-                if (packageSettings != null && packageSettings.size() > 0) {
-                    for (int i = 0, max = packageSettings.size(); i < max; i++) {
-                        final PackageSetting packageSetting = packageSettings.valueAt(i);
-                        if (!shouldFilterApplicationInternal(packageSetting, targetPkgSetting,
-                                userId)) {
-                            return false;
+            } else {
+                for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) {
+                    if (!mFeatureConfig.packageIsEnabled(callingSharedPkgSettings.valueAt(i).pkg)) {
+                        if (DEBUG_LOGGING) {
+                            log(callingSetting, targetPkgSetting, "DISABLED");
                         }
-                        if (callingPkgSetting == null && packageSetting.pkg != null) {
-                            callingPkgSetting = packageSetting;
-                        }
-                    }
-                    if (callingPkgSetting == null) {
-                        Slog.wtf(TAG, callingSetting + " does not have any non-null packages!");
-                        return true;
-                    }
-                } else {
-                    Slog.wtf(TAG, callingSetting + " has no packages!");
-                    return true;
-                }
-            }
-
-            if (DEBUG_LOGGING) {
-                log(callingPkgSetting, targetPkgSetting,
-                        DEBUG_ALLOW_ALL ? "ALLOWED" : "BLOCKED");
-            }
-            return !DEBUG_ALLOW_ALL;
-        } finally {
-            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
-        }
-    }
-
-    private boolean shouldFilterApplicationInternal(
-            PackageSetting callingPkgSetting, PackageSetting targetPkgSetting, int userId) {
-        return shouldFilterApplicationInternal(callingPkgSetting, targetPkgSetting, userId,
-                true /*expandSharedUser*/);
-    }
-
-    /**
-     * @param expandSharedUser true if all members of the shared user a target may belong to should
-     *                         be considered
-     */
-    private boolean shouldFilterApplicationInternal(
-            PackageSetting callingPkgSetting, PackageSetting targetPkgSetting, int userId,
-            boolean expandSharedUser) {
-        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal");
-        try {
-            // special case shared user targets
-            if (expandSharedUser && targetPkgSetting.sharedUser != null) {
-                for (PackageSetting sharedMemberSetting : targetPkgSetting.sharedUser.packages) {
-                    if (!shouldFilterApplicationInternal(
-                            callingPkgSetting, sharedMemberSetting, userId,
-                            false /*expandSharedUser*/)) {
                         return false;
                     }
                 }
-                return true;
             }
 
-            final String callingName = callingPkgSetting.pkg.packageName;
-            final PackageParser.Package targetPkg = targetPkgSetting.pkg;
-
-            if (!mFeatureConfig.packageIsEnabled(callingPkgSetting.pkg)) {
-                if (DEBUG_LOGGING) {
-                    log(callingPkgSetting, targetPkgSetting, "DISABLED");
-                }
-                return false;
-            }
             // This package isn't technically installed and won't be written to settings, so we can
             // treat it as filtered until it's available again.
+            final PackageParser.Package targetPkg = targetPkgSetting.pkg;
             if (targetPkg == null) {
                 if (DEBUG_LOGGING) {
                     Slog.wtf(TAG, "shouldFilterApplication: " + "targetPkg is null");
@@ -488,149 +461,180 @@
                 return true;
             }
             final String targetName = targetPkg.packageName;
-            if (callingPkgSetting.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.R) {
+            final int callingAppId;
+            if (callingPkgSetting != null) {
+                callingAppId = callingPkgSetting.appId;
+            } else {
+                callingAppId = callingSharedPkgSettings.valueAt(0).appId; // all should be the same
+            }
+            final int targetAppId = targetPkgSetting.appId;
+            if (callingAppId == targetAppId) {
                 if (DEBUG_LOGGING) {
-                    log(callingPkgSetting, targetPkgSetting, "caller pre-R");
+                    log(callingSetting, targetPkgSetting, "same app id");
                 }
                 return false;
             }
-            if (callingPkgSetting.appId == targetPkgSetting.appId) {
+
+            if (callingSetting.getPermissionsState().hasPermission(
+                    Manifest.permission.QUERY_ALL_PACKAGES, UserHandle.getUserId(callingUid))) {
                 if (DEBUG_LOGGING) {
-                    log(callingPkgSetting, targetPkgSetting, "same app id");
+                    log(callingSetting, targetPkgSetting, "has query-all permission");
                 }
                 return false;
             }
-            if (isImplicitlyQueryableSystemApp(targetPkgSetting)) {
+            if (mForceQueryable.contains(targetAppId)) {
                 if (DEBUG_LOGGING) {
-                    log(callingPkgSetting, targetPkgSetting, "implicitly queryable sys");
+                    log(callingSetting, targetPkgSetting, "force queryable");
                 }
                 return false;
             }
-            if (targetPkg.mForceQueryable) {
-                if (DEBUG_LOGGING) {
-                    log(callingPkgSetting, targetPkgSetting, "manifest forceQueryable");
-                }
-                return false;
-            }
-            if (mForceQueryable.contains(targetName)) {
-                if (DEBUG_LOGGING) {
-                    log(callingPkgSetting, targetPkgSetting, "whitelist forceQueryable");
-                }
-                return false;
-            }
-            if (mQueriesViaPackage.containsKey(callingName)
-                    && mQueriesViaPackage.get(callingName).contains(
-                    targetName)) {
+            if (mQueriesViaPackage.contains(callingAppId, targetAppId)) {
                 // the calling package has explicitly declared the target package; allow
                 if (DEBUG_LOGGING) {
-                    log(callingPkgSetting, targetPkgSetting, "queries package");
+                    log(callingSetting, targetPkgSetting, "queries package");
                 }
                 return false;
-            } else if (mQueriesViaIntent.containsKey(callingName)
-                    && mQueriesViaIntent.get(callingName).contains(targetName)) {
+            } else if (mQueriesViaIntent.contains(callingAppId, targetAppId)) {
                 if (DEBUG_LOGGING) {
-                    log(callingPkgSetting, targetPkgSetting, "queries intent");
+                    log(callingSetting, targetPkgSetting, "queries intent");
                 }
                 return false;
             }
-            if (mImplicitlyQueryable.get(userId) != null
-                    && mImplicitlyQueryable.get(userId).containsKey(callingName)
-                    && mImplicitlyQueryable.get(userId).get(callingName).contains(targetName)) {
+
+            final int targetUid = UserHandle.getUid(userId, targetAppId);
+            if (mImplicitlyQueryable.contains(callingUid, targetUid)) {
                 if (DEBUG_LOGGING) {
-                    log(callingPkgSetting, targetPkgSetting, "implicitly queryable for user");
+                    log(callingSetting, targetPkgSetting, "implicitly queryable for user");
                 }
                 return false;
             }
-            final ArrayList<PackageParser.Instrumentation> inst =
-                    callingPkgSetting.pkg.instrumentation;
-            if (inst.size() > 0) {
-                for (int i = 0, max = inst.size(); i < max; i++) {
-                    if (inst.get(i).info.targetPackage == targetName) {
-                        if (DEBUG_LOGGING) {
-                            log(callingPkgSetting, targetPkgSetting, "instrumentation");
-                        }
+            if (callingPkgSetting != null) {
+                if (callingPkgInstruments(callingPkgSetting, targetPkgSetting, targetName)) {
+                    return false;
+                }
+            } else {
+                for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) {
+                    if (callingPkgInstruments(callingSharedPkgSettings.valueAt(i),
+                            targetPkgSetting, targetName)) {
                         return false;
                     }
                 }
             }
-            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.checkPermission");
-            try {
-                if (mPermissionManager.checkPermission(
-                        Manifest.permission.QUERY_ALL_PACKAGES, callingName, userId)
-                        == PackageManager.PERMISSION_GRANTED) {
-                    if (DEBUG_LOGGING) {
-                        log(callingPkgSetting, targetPkgSetting, "permission");
-                    }
-                    return false;
-                }
-            } catch (RemoteException e) {
-                return true;
-            } finally {
-                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
-            }
             return true;
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
     }
 
-    private static void log(PackageSetting callingPkgSetting, PackageSetting targetPkgSetting,
-            String description) {
-        Slog.wtf(TAG,
-                "interaction: " + callingPkgSetting.name + " -> " + targetPkgSetting.name + " "
-                        + description);
+    private static boolean callingPkgInstruments(PackageSetting callingPkgSetting,
+            PackageSetting targetPkgSetting,
+            String targetName) {
+        final ArrayList<PackageParser.Instrumentation> inst = callingPkgSetting.pkg.instrumentation;
+        for (int i = inst.size() - 1; i >= 0; i--) {
+            if (inst.get(i).info.targetPackage == targetName) {
+                if (DEBUG_LOGGING) {
+                    log(callingPkgSetting, targetPkgSetting, "instrumentation");
+                }
+                return true;
+            }
+        }
+        return false;
     }
 
-    private boolean isImplicitlyQueryableSystemApp(PackageSetting targetPkgSetting) {
-        return targetPkgSetting.isSystem() && (mSystemAppsQueryable
-                || mForceQueryableByDevice.contains(targetPkgSetting.pkg.packageName));
+    private static void log(SettingBase callingPkgSetting, PackageSetting targetPkgSetting,
+            String description) {
+        log(callingPkgSetting, targetPkgSetting, description, null);
+    }
+
+    private static void log(SettingBase callingPkgSetting, PackageSetting targetPkgSetting,
+            String description, Throwable throwable) {
+        Slog.wtf(TAG,
+                "interaction: " + callingPkgSetting.toString()
+                        + " -> " + targetPkgSetting.name + " "
+                        + description, throwable);
     }
 
     public void dumpQueries(
-            PrintWriter pw, @Nullable String filteringPackageName, DumpState dumpState,
+            PrintWriter pw, PackageManagerService pms, @Nullable Integer filteringAppId,
+            DumpState dumpState,
             int[] users) {
+        final SparseArray<String> cache = new SparseArray<>();
+        ToString<Integer> expandPackages = input -> {
+            String cachedValue = cache.get(input);
+            if (cachedValue == null) {
+                final String[] packagesForUid = pms.getPackagesForUid(input);
+                if (packagesForUid == null) {
+                    cachedValue = "[unknown app id " + input + "]";
+                } else {
+                    cachedValue = packagesForUid.length == 1 ? packagesForUid[0]
+                            : "[" + TextUtils.join(",", packagesForUid) + "]";
+                }
+                cache.put(input, cachedValue);
+            }
+            return cachedValue;
+        };
         pw.println();
         pw.println("Queries:");
         dumpState.onTitlePrinted();
+        if (!mFeatureConfig.isGloballyEnabled()) {
+            pw.println("  DISABLED");
+            if (!DEBUG_LOGGING) {
+                return;
+            }
+        }
         pw.println("  system apps queryable: " + mSystemAppsQueryable);
-        dumpPackageSet(pw, filteringPackageName, mForceQueryableByDevice, "System whitelist", "  ");
-        dumpPackageSet(pw, filteringPackageName, mForceQueryable, "forceQueryable", "  ");
+        dumpPackageSet(pw, filteringAppId, mForceQueryable, "forceQueryable", "  ", expandPackages);
         pw.println("  queries via package name:");
-        dumpQueriesMap(pw, filteringPackageName, mQueriesViaPackage, "    ");
+        dumpQueriesMap(pw, filteringAppId, mQueriesViaPackage, "    ", expandPackages);
         pw.println("  queries via intent:");
-        dumpQueriesMap(pw, filteringPackageName, mQueriesViaIntent, "    ");
+        dumpQueriesMap(pw, filteringAppId, mQueriesViaIntent, "    ", expandPackages);
         pw.println("  queryable via interaction:");
         for (int user : users) {
             pw.append("    User ").append(Integer.toString(user)).println(":");
-            final HashMap<String, Set<String>> queryMapForUser = mImplicitlyQueryable.get(user);
-            if (queryMapForUser != null) {
-                dumpQueriesMap(pw, filteringPackageName, queryMapForUser, "      ");
-            }
+            dumpQueriesMap(pw,
+                    filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId),
+                    mImplicitlyQueryable, "      ", expandPackages);
         }
     }
 
-    private static void dumpQueriesMap(PrintWriter pw, @Nullable String filteringPackageName,
-            HashMap<String, Set<String>> queriesMap, String spacing) {
-        for (String callingPkg : queriesMap.keySet()) {
-            if (Objects.equals(callingPkg, filteringPackageName)) {
-                // don't filter target package names if the calling is filteringPackageName
-                dumpPackageSet(pw, null /*filteringPackageName*/, queriesMap.get(callingPkg),
-                        callingPkg, spacing);
+    private static void dumpQueriesMap(PrintWriter pw, @Nullable Integer filteringId,
+            SparseSetArray<Integer> queriesMap, String spacing,
+            @Nullable ToString<Integer> toString) {
+        for (int i = 0; i < queriesMap.size(); i++) {
+            Integer callingId = queriesMap.keyAt(i);
+            if (Objects.equals(callingId, filteringId)) {
+                // don't filter target package names if the calling is filteringId
+                dumpPackageSet(
+                        pw, null /*filteringId*/, queriesMap.get(callingId),
+                        toString == null
+                                ? callingId.toString()
+                                : toString.toString(callingId),
+                        spacing, toString);
             } else {
-                dumpPackageSet(pw, filteringPackageName, queriesMap.get(callingPkg), callingPkg,
-                        spacing);
+                dumpPackageSet(
+                        pw, filteringId, queriesMap.get(callingId),
+                        toString == null
+                                ? callingId.toString()
+                                : toString.toString(callingId),
+                        spacing, toString);
             }
         }
     }
 
-    private static void dumpPackageSet(PrintWriter pw, @Nullable String filteringPackageName,
-            Set<String> targetPkgSet, String subTitle, String spacing) {
+    private interface ToString<T> {
+        String toString(T input);
+    }
+
+    private static <T> void dumpPackageSet(PrintWriter pw, @Nullable T filteringId,
+            Set<T> targetPkgSet, String subTitle, String spacing,
+            @Nullable ToString<T> toString) {
         if (targetPkgSet != null && targetPkgSet.size() > 0
-                && (filteringPackageName == null || targetPkgSet.contains(filteringPackageName))) {
+                && (filteringId == null || targetPkgSet.contains(filteringId))) {
             pw.append(spacing).append(subTitle).println(":");
-            for (String pkgName : targetPkgSet) {
-                if (filteringPackageName == null || Objects.equals(filteringPackageName, pkgName)) {
-                    pw.append(spacing).append("  ").println(pkgName);
+            for (T item : targetPkgSet) {
+                if (filteringId == null || Objects.equals(filteringId, item)) {
+                    pw.append(spacing).append("  ")
+                            .println(toString == null ? item : toString.toString(item));
                 }
             }
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index fe82f7c..fa98c96 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11701,7 +11701,7 @@
             ksms.addScannedPackageLPw(pkg);
 
             mComponentResolver.addAllComponents(pkg, chatty);
-            mAppsFilter.addPackage(pkg, mPackages);
+            mAppsFilter.addPackage(pkgSetting, mSettings.mPackages);
 
             // Don't allow ephemeral applications to define new permissions groups.
             if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
@@ -11889,31 +11889,10 @@
         }
     }
 
-    void removeInstalledPackageLI(PackageParser.Package pkg, boolean chatty) {
-        if (DEBUG_INSTALL) {
-            if (chatty)
-                Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName);
-        }
-
-        // writer
-        synchronized (mLock) {
-            // Remove the parent package
-            mPackages.remove(pkg.applicationInfo.packageName);
-            cleanPackageDataStructuresLILPw(pkg, chatty);
-
-            // Remove the child packages
-            final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
-            for (int i = 0; i < childCount; i++) {
-                PackageParser.Package childPkg = pkg.childPackages.get(i);
-                mPackages.remove(childPkg.applicationInfo.packageName);
-                cleanPackageDataStructuresLILPw(childPkg, chatty);
-            }
-        }
-    }
-
     void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
         mComponentResolver.removeAllComponents(pkg, chatty);
-        mAppsFilter.removePackage(pkg.packageName);
+        mAppsFilter.removePackage((PackageSetting) pkg.mExtras,
+                mInjector.getUserManagerInternal().getUserIds(), mSettings.mPackages);
         mPermissionManager.removeAllPermissions(pkg, chatty);
 
         final int instrumentationSize = pkg.instrumentation.size();
@@ -20861,7 +20840,11 @@
             }
 
             if (dumpState.isDumping(DumpState.DUMP_QUERIES)) {
-                mAppsFilter.dumpQueries(pw, packageName, dumpState, mUserManager.getUserIds());
+                final PackageSetting setting = mSettings.getPackageLPr(packageName);
+                Integer filteringAppId = setting == null ? null : setting.appId;
+                mAppsFilter.dumpQueries(
+                        pw, this, filteringAppId, dumpState,
+                        mUserManager.getUserIds());
             }
 
             if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
@@ -23195,8 +23178,9 @@
                 int callingUid, int targetAppId) {
             synchronized (mLock) {
                 final PackageParser.Package callingPackage = getPackage(callingUid);
+                final int targetUid = UserHandle.getUid(userId, targetAppId);
                 final PackageParser.Package targetPackage =
-                        getPackage(UserHandle.getUid(userId, targetAppId));
+                        getPackage(targetUid);
                 if (callingPackage == null || targetPackage == null) {
                     return;
                 }
@@ -23207,8 +23191,7 @@
                     mInstantAppRegistry.grantInstantAccessLPw(userId, intent,
                             UserHandle.getAppId(callingUid), targetAppId);
                 } else {
-                    mAppsFilter.grantImplicitAccess(
-                            callingPackage.packageName, targetPackage.packageName, userId);
+                    mAppsFilter.grantImplicitAccess(callingUid, targetUid);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionsState.java b/services/core/java/com/android/server/pm/permission/PermissionsState.java
index 505a0e2..b68d541 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionsState.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionsState.java
@@ -23,6 +23,7 @@
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.ArrayUtils;
 
 import java.util.ArrayList;
@@ -30,7 +31,6 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
-import com.android.internal.annotations.GuardedBy;
 
 /**
  * This class encapsulates the permissions for a package or a shared user.
@@ -708,7 +708,11 @@
     }
 
     private static final class PermissionData {
+
+        private final Object mLock = new Object();
+
         private final BasePermission mPerm;
+        @GuardedBy("mLock")
         private SparseArray<PermissionState> mUserStates = new SparseArray<>();
 
         public PermissionData(BasePermission perm) {
@@ -717,11 +721,14 @@
 
         public PermissionData(PermissionData other) {
             this(other.mPerm);
-            final int otherStateCount = other.mUserStates.size();
-            for (int i = 0; i < otherStateCount; i++) {
-                final int otherUserId = other.mUserStates.keyAt(i);
-                PermissionState otherState = other.mUserStates.valueAt(i);
-                mUserStates.put(otherUserId, new PermissionState(otherState));
+
+            synchronized (mLock) {
+                final int otherStateCount = other.mUserStates.size();
+                for (int i = 0; i < otherStateCount; i++) {
+                    final int otherUserId = other.mUserStates.keyAt(i);
+                    PermissionState otherState = other.mUserStates.valueAt(i);
+                    mUserStates.put(otherUserId, new PermissionState(otherState));
+                }
             }
         }
 
@@ -730,71 +737,83 @@
         }
 
         public boolean isGranted(int userId) {
-            if (isInstallPermission()) {
-                userId = UserHandle.USER_ALL;
-            }
+            synchronized (mLock) {
+                if (isInstallPermission()) {
+                    userId = UserHandle.USER_ALL;
+                }
 
-            PermissionState userState = mUserStates.get(userId);
-            if (userState == null) {
-                return false;
-            }
+                PermissionState userState = mUserStates.get(userId);
+                if (userState == null) {
+                    return false;
+                }
 
-            return userState.mGranted;
+                return userState.mGranted;
+            }
         }
 
         public boolean grant(int userId) {
-            if (!isCompatibleUserId(userId)) {
-                return false;
+            synchronized (mLock) {
+                if (!isCompatibleUserId(userId)) {
+                    return false;
+                }
+
+                if (isGranted(userId)) {
+                    return false;
+                }
+
+                PermissionState userState = mUserStates.get(userId);
+                if (userState == null) {
+                    userState = new PermissionState(mPerm.getName());
+                    mUserStates.put(userId, userState);
+                }
+
+                userState.mGranted = true;
+
+                return true;
             }
-
-            if (isGranted(userId)) {
-                return false;
-            }
-
-            PermissionState userState = mUserStates.get(userId);
-            if (userState == null) {
-                userState = new PermissionState(mPerm.getName());
-                mUserStates.put(userId, userState);
-            }
-
-            userState.mGranted = true;
-
-            return true;
         }
 
         public boolean revoke(int userId) {
-            if (!isCompatibleUserId(userId)) {
-                return false;
+            synchronized (mLock) {
+                if (!isCompatibleUserId(userId)) {
+                    return false;
+                }
+
+                if (!isGranted(userId)) {
+                    return false;
+                }
+
+                PermissionState userState = mUserStates.get(userId);
+                userState.mGranted = false;
+
+                if (userState.isDefault()) {
+                    mUserStates.remove(userId);
+                }
+
+                return true;
             }
-
-            if (!isGranted(userId)) {
-                return false;
-            }
-
-            PermissionState userState = mUserStates.get(userId);
-            userState.mGranted = false;
-
-            if (userState.isDefault()) {
-                mUserStates.remove(userId);
-            }
-
-            return true;
         }
 
         public PermissionState getPermissionState(int userId) {
-            return mUserStates.get(userId);
+            synchronized (mLock) {
+                return mUserStates.get(userId);
+            }
         }
 
         public int getFlags(int userId) {
-            PermissionState userState = mUserStates.get(userId);
-            if (userState != null) {
-                return userState.mFlags;
+            synchronized (mLock) {
+                PermissionState userState = mUserStates.get(userId);
+                if (userState != null) {
+                    return userState.mFlags;
+                }
+                return 0;
             }
-            return 0;
         }
 
         public boolean isDefault() {
-            return mUserStates.size() <= 0;
+            synchronized (mLock) {
+                return mUserStates.size() <= 0;
+            }
         }
 
         public static boolean isInstallPermissionKey(int userId) {
@@ -802,32 +821,34 @@
         }
 
         public boolean updateFlags(int userId, int flagMask, int flagValues) {
-            if (isInstallPermission()) {
-                userId = UserHandle.USER_ALL;
-            }
+            synchronized (mLock) {
+                if (isInstallPermission()) {
+                    userId = UserHandle.USER_ALL;
+                }
 
-            if (!isCompatibleUserId(userId)) {
+                if (!isCompatibleUserId(userId)) {
+                    return false;
+                }
+
+                final int newFlags = flagValues & flagMask;
+
+                PermissionState userState = mUserStates.get(userId);
+                if (userState != null) {
+                    final int oldFlags = userState.mFlags;
+                    userState.mFlags = (userState.mFlags & ~flagMask) | newFlags;
+                    if (userState.isDefault()) {
+                        mUserStates.remove(userId);
+                    }
+                    return userState.mFlags != oldFlags;
+                } else if (newFlags != 0) {
+                    userState = new PermissionState(mPerm.getName());
+                    userState.mFlags = newFlags;
+                    mUserStates.put(userId, userState);
+                    return true;
+                }
+
                 return false;
             }
-
-            final int newFlags = flagValues & flagMask;
-
-            PermissionState userState = mUserStates.get(userId);
-            if (userState != null) {
-                final int oldFlags = userState.mFlags;
-                userState.mFlags = (userState.mFlags & ~flagMask) | newFlags;
-                if (userState.isDefault()) {
-                    mUserStates.remove(userId);
-                }
-                return userState.mFlags != oldFlags;
-            } else if (newFlags != 0) {
-                userState = new PermissionState(mPerm.getName());
-                userState.mFlags = newFlags;
-                mUserStates.put(userId, userState);
-                return true;
-            }
-
-            return false;
         }
 
         private boolean isCompatibleUserId(int userId) {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 91c909d..a91998a 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -539,6 +539,7 @@
         mRootActivityContainer = mService.mRootActivityContainer;
         mHandler = new ActivityStackHandler(supervisor.mLooper);
         mWindowManager = mService.mWindowManager;
+        mRemoteToken = new RemoteToken(this);
         mCurrentUser = mService.mAmInternal.getCurrentUserId();
         // Set display id before setting activity and window type to make sure it won't affect
         // stacks on a wrong display.
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 3ef848c..79c76b9 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3243,7 +3243,7 @@
 
     private void sanitizeAndApplyConfigChange(ConfigurationContainer container,
             WindowContainerTransaction.Change change) {
-        if (!(container instanceof Task)) {
+        if (!(container instanceof Task || container instanceof ActivityStack)) {
             throw new RuntimeException("Invalid token in task transaction");
         }
         // The "client"-facing API should prevent bad changes; however, just in case, sanitize
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 5a21016..06cce52 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -1250,6 +1250,7 @@
         stack.getBounds(info.bounds);
         info.displayId = displayId;
         info.stackId = stack.mStackId;
+        info.stackToken = stack.mRemoteToken;
         info.userId = stack.mCurrentUser;
         info.visible = stack.shouldBeVisible(null);
         // A stack might be not attached to a display.
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index f7b802d..a867a5d4 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -133,14 +133,15 @@
 
         @Override
         public void onInputEvent(InputEvent event) {
-            if (!(event instanceof MotionEvent)
-                    || (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
-                return;
-            }
-            final MotionEvent motionEvent = (MotionEvent) event;
             boolean handled = false;
-
             try {
+                // All returns need to be in the try block to make sure the finishInputEvent is
+                // called correctly.
+                if (!(event instanceof MotionEvent)
+                        || (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
+                    return;
+                }
+                final MotionEvent motionEvent = (MotionEvent) event;
                 if (mDragEnded) {
                     // The drag has ended but the clean-up message has not been processed by
                     // window manager. Drop events that occur after this until window manager
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f1dbd7b..99f484e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1945,7 +1945,7 @@
         }
 
         TelephonyManager getTelephonyManager() {
-            return TelephonyManager.from(mContext);
+            return mContext.getSystemService(TelephonyManager.class);
         }
 
         TrustManager getTrustManager() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index 9c97305..45de451 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -33,6 +33,8 @@
 import static com.android.server.DeviceIdleController.LIGHT_STATE_PRE_IDLE;
 import static com.android.server.DeviceIdleController.LIGHT_STATE_WAITING_FOR_NETWORK;
 import static com.android.server.DeviceIdleController.MSG_REPORT_STATIONARY_STATUS;
+import static com.android.server.DeviceIdleController.MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR;
+import static com.android.server.DeviceIdleController.MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR;
 import static com.android.server.DeviceIdleController.STATE_ACTIVE;
 import static com.android.server.DeviceIdleController.STATE_IDLE;
 import static com.android.server.DeviceIdleController.STATE_IDLE_MAINTENANCE;
@@ -180,7 +182,9 @@
                 mHandler = controller.new MyHandler(getContext().getMainLooper());
                 spyOn(mHandler);
                 doNothing().when(mHandler).handleMessage(argThat((message) ->
-                        message.what != MSG_REPORT_STATIONARY_STATUS));
+                        message.what != MSG_REPORT_STATIONARY_STATUS
+                        && message.what != MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR
+                        && message.what != MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR));
                 doAnswer(new Answer<Boolean>() {
                     @Override
                     public Boolean answer(InvocationOnMock invocation) throws Throwable {
@@ -189,7 +193,9 @@
                         return true;
                     }
                 }).when(mHandler).sendMessageDelayed(
-                        argThat((message) -> message.what == MSG_REPORT_STATIONARY_STATUS),
+                        argThat((message) -> message.what == MSG_REPORT_STATIONARY_STATUS
+                                || message.what == MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR
+                                || message.what == MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR),
                         anyLong());
             }
 
@@ -1734,13 +1740,11 @@
             }
             //TODO(b/123045185): Mocked Handler of DeviceIdleController to make message loop
             //workable in this test class
-            mDeviceIdleController.updatePreIdleFactor();
             float expectedfactor = mDeviceIdleController.getPreIdleTimeoutByMode(mode);
             float curfactor = mDeviceIdleController.getPreIdleTimeoutFactor();
             assertEquals("Pre idle time factor of mode [" + mode + "].",
                     expectedfactor, curfactor, delta);
             mDeviceIdleController.resetPreIdleTimeoutMode();
-            mDeviceIdleController.updatePreIdleFactor();
 
             checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_INACTIVE);
             checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_IDLE_PENDING);
@@ -2088,14 +2092,11 @@
                         mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK, ret);
             }
             if (ret == mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK) {
-                mDeviceIdleController.updatePreIdleFactor();
                 long newAlarm = mDeviceIdleController.getNextAlarmTime();
                 long newDelay = (long) ((alarm - now) * factor);
                 assertTrue("setPreIdleTimeoutFactor: " + factor,
                         Math.abs(newDelay - (newAlarm - now)) <  errorTolerance);
                 mDeviceIdleController.resetPreIdleTimeoutMode();
-                mDeviceIdleController.updatePreIdleFactor();
-                mDeviceIdleController.maybeDoImmediateMaintenance();
                 newAlarm = mDeviceIdleController.getNextAlarmTime();
                 assertTrue("resetPreIdleTimeoutMode from: " + factor,
                         Math.abs(newAlarm - alarm) < errorTolerance);
@@ -2106,19 +2107,14 @@
                 assertTrue("setPreIdleTimeoutFactor: " + factor + " before step to idle",
                         Math.abs(newDelay - (newAlarm - now)) <  errorTolerance);
                 mDeviceIdleController.resetPreIdleTimeoutMode();
-                mDeviceIdleController.updatePreIdleFactor();
-                mDeviceIdleController.maybeDoImmediateMaintenance();
             }
         } else {
             mDeviceIdleController.setPreIdleTimeoutFactor(factor);
-            mDeviceIdleController.updatePreIdleFactor();
             long newAlarm = mDeviceIdleController.getNextAlarmTime();
             assertTrue("setPreIdleTimeoutFactor: " + factor
                     + " shounld not change next alarm" ,
                     (newAlarm == alarm));
             mDeviceIdleController.resetPreIdleTimeoutMode();
-            mDeviceIdleController.updatePreIdleFactor();
-            mDeviceIdleController.maybeDoImmediateMaintenance();
         }
     }
 
@@ -2138,18 +2134,15 @@
             long alarm = mDeviceIdleController.getNextAlarmTime();
             mDeviceIdleController.setIdleStartTimeForTest(
                     now - (long) (mConstants.IDLE_TIMEOUT * 0.6));
-            mDeviceIdleController.maybeDoImmediateMaintenance();
             long newAlarm = mDeviceIdleController.getNextAlarmTime();
             assertTrue("maintenance not reschedule IDLE_TIMEOUT * 0.6",
                     newAlarm == alarm);
             mDeviceIdleController.setIdleStartTimeForTest(
                     now - (long) (mConstants.IDLE_TIMEOUT * 1.2));
-            mDeviceIdleController.maybeDoImmediateMaintenance();
             newAlarm = mDeviceIdleController.getNextAlarmTime();
             assertTrue("maintenance not reschedule IDLE_TIMEOUT * 1.2",
                     (newAlarm - now) < minuteInMillis);
             mDeviceIdleController.resetPreIdleTimeoutMode();
-            mDeviceIdleController.updatePreIdleFactor();
         }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index 7081d2e..1d04c83 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -37,6 +37,7 @@
 import android.hardware.SensorEventListener;
 import android.hardware.display.AmbientBrightnessDayStats;
 import android.hardware.display.BrightnessChangeEvent;
+import android.hardware.display.BrightnessConfiguration;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayedContentSample;
 import android.hardware.display.DisplayedContentSamplingAttributes;
@@ -78,6 +79,7 @@
 @RunWith(AndroidJUnit4.class)
 public class BrightnessTrackerTest {
     private static final float DEFAULT_INITIAL_BRIGHTNESS = 2.5f;
+    private static final boolean DEFAULT_COLOR_SAMPLING_ENABLED = true;
     private static final float FLOAT_DELTA = 0.01f;
 
     private BrightnessTracker mTracker;
@@ -151,6 +153,40 @@
     }
 
     @Test
+    public void testModifyBrightnessConfiguration() {
+        mInjector.mInteractive = true;
+        // Start with tracker not listening for color samples.
+        startTracker(mTracker, DEFAULT_INITIAL_BRIGHTNESS, /* collectColorSamples= */ false);
+        assertFalse(mInjector.mColorSamplingEnabled);
+
+        // Update brightness config to enabled color sampling.
+        mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
+                /* collectColorSamples= */ true));
+        mInjector.waitForHandler();
+        assertTrue(mInjector.mColorSamplingEnabled);
+
+        // Update brightness config to disable color sampling.
+        mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
+                /* collectColorSamples= */ false));
+        mInjector.waitForHandler();
+        assertFalse(mInjector.mColorSamplingEnabled);
+
+        // Pretend screen is off, update config to turn on color sampling.
+        mInjector.sendScreenChange(/*screen on */ false);
+        mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
+                /* collectColorSamples= */ true));
+        mInjector.waitForHandler();
+        assertFalse(mInjector.mColorSamplingEnabled);
+
+        // Pretend screen is on.
+        mInjector.sendScreenChange(/*screen on */ true);
+        assertTrue(mInjector.mColorSamplingEnabled);
+
+        mTracker.stop();
+        assertFalse(mInjector.mColorSamplingEnabled);
+    }
+
+    @Test
     public void testNoColorSampling_WrongPixelFormat() {
         mInjector.mDefaultSamplingAttributes =
                 new DisplayedContentSamplingAttributes(
@@ -278,7 +314,7 @@
         mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_ACTIVATED, 1);
         mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, 3333);
 
-        startTracker(mTracker, initialBrightness);
+        startTracker(mTracker, initialBrightness, DEFAULT_COLOR_SAMPLING_ENABLED);
         mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(),
                 batteryChangeEvent(30, 60));
         mInjector.mSensorListener.onSensorChanged(createSensorEvent(1000.0f));
@@ -311,7 +347,7 @@
     @Test
     public void testIgnoreAutomaticBrightnessChange() {
         final int initialBrightness = 30;
-        startTracker(mTracker, initialBrightness);
+        startTracker(mTracker, initialBrightness, DEFAULT_COLOR_SAMPLING_ENABLED);
         mInjector.mSensorListener.onSensorChanged(createSensorEvent(1.0f));
         mInjector.incrementTime(TimeUnit.SECONDS.toMillis(1));
 
@@ -750,11 +786,13 @@
     }
 
     private void startTracker(BrightnessTracker tracker) {
-        startTracker(tracker, DEFAULT_INITIAL_BRIGHTNESS);
+        startTracker(tracker, DEFAULT_INITIAL_BRIGHTNESS,  DEFAULT_COLOR_SAMPLING_ENABLED);
     }
 
-    private void startTracker(BrightnessTracker tracker, float initialBrightness) {
+    private void startTracker(BrightnessTracker tracker, float initialBrightness,
+            boolean collectColorSamples) {
         tracker.start(initialBrightness);
+        tracker.setBrightnessConfiguration(buildBrightnessConfiguration(collectColorSamples));
         mInjector.waitForHandler();
     }
 
@@ -772,6 +810,14 @@
         mInjector.waitForHandler();
     }
 
+    private BrightnessConfiguration buildBrightnessConfiguration(boolean collectColorSamples) {
+        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
+                /* lux = */ new float[] {0f, 10f, 100f},
+                /* nits = */ new float[] {1f, 90f, 100f});
+        builder.setShouldCollectColorSamples(collectColorSamples);
+        return builder.build();
+    }
+
     private static final class Idle implements MessageQueue.IdleHandler {
         private boolean mIdle;
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 819091c..f6fb6e2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -20,20 +20,17 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.annotation.Nullable;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
 import android.os.Build;
 import android.os.Process;
-import android.permission.IPermissionManager;
 import android.util.ArrayMap;
 
 import org.junit.Before;
@@ -43,20 +40,16 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.Map;
-
 @RunWith(JUnit4.class)
 public class AppsFilterTest {
 
     private static final int DUMMY_CALLING_UID = 10345;
-
-    @Mock
-    IPermissionManager mPermissionManagerMock;
+    private static final int DUMMY_TARGET_UID = 10556;
 
     @Mock
     AppsFilter.FeatureConfig mFeatureConfigMock;
 
-    private Map<String, PackageParser.Package> mExisting = new ArrayMap<>();
+    private ArrayMap<String, PackageSetting> mExisting = new ArrayMap<>();
 
     private static PackageBuilder pkg(String packageName) {
         return new PackageBuilder(packageName)
@@ -72,9 +65,10 @@
     }
 
     private static PackageBuilder pkg(String packageName, IntentFilter... filters) {
+        final ActivityInfo activityInfo = new ActivityInfo();
         final PackageBuilder packageBuilder = pkg(packageName).addActivity(
                 pkg -> new PackageParser.ParseComponentArgs(pkg, new String[1], 0, 0, 0, 0, 0, 0,
-                        new String[]{packageName}, 0, 0, 0), new ActivityInfo());
+                        new String[]{packageName}, 0, 0, 0), activityInfo);
         for (IntentFilter filter : filters) {
             packageBuilder.addActivityIntentInfo(0 /* index */, activity -> {
                 final PackageParser.ActivityIntentInfo info =
@@ -83,7 +77,7 @@
                     filter.actionsIterator().forEachRemaining(info::addAction);
                 }
                 if (filter.countCategories() > 0) {
-                    filter.actionsIterator().forEachRemaining(info::addAction);
+                    filter.actionsIterator().forEachRemaining(info::addCategory);
                 }
                 if (filter.countDataAuthorities() > 0) {
                     filter.authoritiesIterator().forEachRemaining(info::addDataAuthority);
@@ -91,6 +85,7 @@
                 if (filter.countDataSchemes() > 0) {
                     filter.schemesIterator().forEachRemaining(info::addDataScheme);
                 }
+                activityInfo.exported = true;
                 return info;
             });
         }
@@ -102,9 +97,6 @@
         mExisting = new ArrayMap<>();
 
         MockitoAnnotations.initMocks(this);
-        when(mPermissionManagerMock
-                .checkPermission(anyString(), anyString(), anyInt()))
-                .thenReturn(PackageManager.PERMISSION_DENIED);
         when(mFeatureConfigMock.isGloballyEnabled()).thenReturn(true);
         when(mFeatureConfigMock.packageIsEnabled(any(PackageParser.Package.class)))
                 .thenReturn(true);
@@ -113,7 +105,7 @@
     @Test
     public void testSystemReadyPropogates() throws Exception {
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock, new String[]{}, false);
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false);
         appsFilter.onSystemReady();
         verify(mFeatureConfigMock).onSystemReady();
     }
@@ -121,12 +113,12 @@
     @Test
     public void testQueriesAction_FilterMatches() {
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock, new String[]{}, false);
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false);
 
         PackageSetting target = simulateAddPackage(appsFilter,
-                pkg("com.some.package", new IntentFilter("TEST_ACTION"))).build();
+                pkg("com.some.package", new IntentFilter("TEST_ACTION")), DUMMY_TARGET_UID);
         PackageSetting calling = simulateAddPackage(appsFilter,
-                pkg("com.some.other.package", new Intent("TEST_ACTION"))).build();
+                pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_UID);
 
         assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
     }
@@ -134,12 +126,12 @@
     @Test
     public void testQueriesAction_NoMatchingAction_Filters() {
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock, new String[]{}, false);
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false);
 
         PackageSetting target = simulateAddPackage(appsFilter,
-                pkg("com.some.package")).build();
+                pkg("com.some.package"), DUMMY_TARGET_UID);
         PackageSetting calling = simulateAddPackage(appsFilter,
-                pkg("com.some.other.package", new Intent("TEST_ACTION"))).build();
+                pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_UID);
 
         assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
     }
@@ -147,13 +139,17 @@
     @Test
     public void testQueriesAction_NoMatchingActionFilterLowSdk_DoesntFilter() {
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
-                        new String[]{}, false);
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false);
 
-        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
-        PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package",
-                new Intent("TEST_ACTION")).setApplicationInfoTargetSdkVersion(
-                Build.VERSION_CODES.P)).build();
+        PackageSetting target = simulateAddPackage(appsFilter,
+                pkg("com.some.package"), DUMMY_TARGET_UID);
+        PackageSetting calling = simulateAddPackage(appsFilter,
+                pkg("com.some.other.package",
+                        new Intent("TEST_ACTION"))
+                        .setApplicationInfoTargetSdkVersion(Build.VERSION_CODES.P),
+                DUMMY_CALLING_UID);
+
+        when(mFeatureConfigMock.packageIsEnabled(calling.pkg)).thenReturn(false);
 
         assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
     }
@@ -161,12 +157,12 @@
     @Test
     public void testNoQueries_Filters() {
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
-                        new String[]{}, false);
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false);
 
-        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
+        PackageSetting target = simulateAddPackage(appsFilter,
+                pkg("com.some.package"), DUMMY_TARGET_UID);
         PackageSetting calling = simulateAddPackage(appsFilter,
-                pkg("com.some.other.package")).build();
+                pkg("com.some.other.package"), DUMMY_CALLING_UID);
 
         assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
     }
@@ -174,14 +170,12 @@
     @Test
     public void testForceQueryable_DoesntFilter() {
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
-                        new String[]{}, false);
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false);
 
-        PackageSetting target =
-                simulateAddPackage(appsFilter, pkg("com.some.package").setForceQueryable(true))
-                        .build();
+        PackageSetting target = simulateAddPackage(appsFilter,
+                        pkg("com.some.package").setForceQueryable(true), DUMMY_TARGET_UID);
         PackageSetting calling = simulateAddPackage(appsFilter,
-                pkg("com.some.other.package")).build();
+                pkg("com.some.other.package"), DUMMY_CALLING_UID);
 
         assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
     }
@@ -189,14 +183,13 @@
     @Test
     public void testForceQueryableByDevice_SystemCaller_DoesntFilter() {
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
-                        new String[]{"com.some.package"}, false);
+                new AppsFilter(mFeatureConfigMock, new String[]{"com.some.package"}, false);
 
-        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"))
-                .setPkgFlags(ApplicationInfo.FLAG_SYSTEM)
-                .build();
+        PackageSetting target = simulateAddPackage(appsFilter,
+                pkg("com.some.package"), DUMMY_TARGET_UID,
+                setting -> setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
         PackageSetting calling = simulateAddPackage(appsFilter,
-                pkg("com.some.other.package")).build();
+                pkg("com.some.other.package"), DUMMY_CALLING_UID);
 
         assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
     }
@@ -204,12 +197,12 @@
     @Test
     public void testForceQueryableByDevice_NonSystemCaller_Filters() {
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
-                        new String[]{"com.some.package"}, false);
+                new AppsFilter(mFeatureConfigMock, new String[]{"com.some.package"}, false);
 
-        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
+        PackageSetting target = simulateAddPackage(appsFilter,
+                pkg("com.some.package"), DUMMY_TARGET_UID);
         PackageSetting calling = simulateAddPackage(appsFilter,
-                pkg("com.some.other.package")).build();
+                pkg("com.some.other.package"), DUMMY_CALLING_UID);
 
         assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
     }
@@ -218,14 +211,14 @@
     @Test
     public void testSystemQueryable_DoesntFilter() {
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
-                        new String[]{}, true /* system force queryable */);
+                new AppsFilter(mFeatureConfigMock, new String[]{},
+                        true /* system force queryable */);
 
-        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"))
-                .setPkgFlags(ApplicationInfo.FLAG_SYSTEM)
-                .build();
+        PackageSetting target = simulateAddPackage(appsFilter,
+                pkg("com.some.package"), DUMMY_TARGET_UID,
+                setting -> setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
         PackageSetting calling = simulateAddPackage(appsFilter,
-                pkg("com.some.other.package")).build();
+                pkg("com.some.other.package"), DUMMY_CALLING_UID);
 
         assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
     }
@@ -233,12 +226,12 @@
     @Test
     public void testQueriesPackage_DoesntFilter() {
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
-                        new String[]{}, false);
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false);
 
-        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
+        PackageSetting target = simulateAddPackage(appsFilter,
+                pkg("com.some.package"), DUMMY_TARGET_UID);
         PackageSetting calling = simulateAddPackage(appsFilter,
-                pkg("com.some.other.package", "com.some.package")).build();
+                pkg("com.some.other.package", "com.some.package"), DUMMY_CALLING_UID);
 
         assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
     }
@@ -248,12 +241,12 @@
         when(mFeatureConfigMock.packageIsEnabled(any(PackageParser.Package.class)))
                 .thenReturn(false);
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
-                        new String[]{}, false);
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false);
 
-        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
-        PackageSetting calling = simulateAddPackage(appsFilter,
-                pkg("com.some.other.package")).build();
+        PackageSetting target = simulateAddPackage(
+                appsFilter, pkg("com.some.package"), DUMMY_TARGET_UID);
+        PackageSetting calling = simulateAddPackage(
+                appsFilter, pkg("com.some.other.package"), DUMMY_CALLING_UID);
 
         assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
     }
@@ -261,10 +254,10 @@
     @Test
     public void testSystemUid_DoesntFilter() {
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
-                        new String[]{}, false);
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false);
 
-        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
+        PackageSetting target = simulateAddPackage(appsFilter,
+                pkg("com.some.package"), DUMMY_TARGET_UID);
 
         assertFalse(appsFilter.shouldFilterApplication(0, null, target, 0));
         assertFalse(appsFilter.shouldFilterApplication(
@@ -274,10 +267,10 @@
     @Test
     public void testNonSystemUid_NoCallingSetting_Filters() {
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
-                        new String[]{}, false);
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false);
 
-        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
+        PackageSetting target = simulateAddPackage(appsFilter,
+                pkg("com.some.package"), DUMMY_TARGET_UID);
 
         assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, null, target, 0));
     }
@@ -285,8 +278,7 @@
     @Test
     public void testNoTargetPackage_filters() {
         final AppsFilter appsFilter =
-                new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
-                        new String[]{}, false);
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false);
 
         PackageSetting target = new PackageSettingBuilder()
                 .setName("com.some.package")
@@ -295,22 +287,36 @@
                 .setPVersionCode(1L)
                 .build();
         PackageSetting calling = simulateAddPackage(appsFilter,
-                pkg("com.some.other.package", new Intent("TEST_ACTION"))).build();
+                pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_UID);
 
         assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
     }
 
-    private PackageSettingBuilder simulateAddPackage(AppsFilter filter,
-            PackageBuilder newPkgBuilder) {
+    private interface WithSettingBuilder {
+        PackageSettingBuilder withBuilder(PackageSettingBuilder builder);
+    }
+
+    private PackageSetting simulateAddPackage(AppsFilter filter,
+            PackageBuilder newPkgBuilder, int appId) {
+        return simulateAddPackage(filter, newPkgBuilder, appId, null);
+    }
+
+    private PackageSetting simulateAddPackage(AppsFilter filter,
+            PackageBuilder newPkgBuilder, int appId, @Nullable WithSettingBuilder action) {
         PackageParser.Package newPkg = newPkgBuilder.build();
-        filter.addPackage(newPkg, mExisting);
-        mExisting.put(newPkg.packageName, newPkg);
-        return new PackageSettingBuilder()
+
+        final PackageSettingBuilder settingBuilder = new PackageSettingBuilder()
                 .setPackage(newPkg)
+                .setAppId(appId)
                 .setName(newPkg.packageName)
                 .setCodePath("/")
                 .setResourcePath("/")
                 .setPVersionCode(1L);
+        final PackageSetting setting =
+                (action == null ? settingBuilder : action.withBuilder(settingBuilder)).build();
+        filter.addPackage(setting, mExisting);
+        mExisting.put(newPkg.packageName, setting);
+        return setting;
     }
 
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
index 06c6314..8d476f6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
@@ -43,6 +43,7 @@
     private String mVolumeUuid;
     private SparseArray<PackageUserState> mUserStates = new SparseArray<>();
     private PackageParser.Package mPkg;
+    private int mAppId;
 
     public PackageSettingBuilder setPackage(PackageParser.Package pkg) {
         this.mPkg = pkg;
@@ -54,6 +55,11 @@
         return this;
     }
 
+    public PackageSettingBuilder setAppId(int appId) {
+        this.mAppId = appId;
+        return this;
+    }
+
     public PackageSettingBuilder setRealName(String realName) {
         this.mRealName = realName;
         return this;
@@ -152,6 +158,7 @@
                 mChildPackageNames, mSharedUserId, mUsesStaticLibraries,
                 mUsesStaticLibrariesVersions);
         packageSetting.pkg = mPkg;
+        packageSetting.appId = mAppId;
         packageSetting.volumeUuid = this.mVolumeUuid;
         for (int i = 0; i < mUserStates.size(); i++) {
             packageSetting.setUserState(mUserStates.keyAt(i), mUserStates.valueAt(i));
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 39aa51a..a23e2f1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -24,6 +25,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.graphics.Rect;
 import android.view.WindowContainerTransaction;
 
@@ -76,5 +78,20 @@
         mService.applyContainerTransaction(t);
         assertEquals(newBounds, task.getBounds());
     }
+
+    @Test
+    public void testStackTransaction() {
+        removeGlobalMinSizeRestriction();
+        final ActivityStack stack = new StackBuilder(mRootActivityContainer)
+                .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
+        ActivityManager.StackInfo info =
+                mService.getStackInfo(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
+        WindowContainerTransaction t = new WindowContainerTransaction();
+        assertEquals(stack.mRemoteToken, info.stackToken);
+        Rect newBounds = new Rect(10, 10, 100, 100);
+        t.setBounds(info.stackToken, new Rect(10, 10, 100, 100));
+        mService.applyContainerTransaction(t);
+        assertEquals(newBounds, stack.getBounds());
+    }
 }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index e0ffb0d..4f2d5d2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -61,6 +61,7 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.UserManager;
 import android.platform.test.annotations.Presubmit;
 import android.util.ArraySet;
 import android.util.SparseBooleanArray;
@@ -92,7 +93,9 @@
     private static final int TEST_USER_1_ID = 10;
     private static final int TEST_QUIET_USER_ID = 20;
     private static final UserInfo DEFAULT_USER_INFO = new UserInfo();
-    private static final UserInfo QUIET_USER_INFO = new UserInfo();
+    private static final UserInfo QUIET_PROFILE_USER_INFO = new UserInfo(TEST_QUIET_USER_ID,
+            "quiet_profile", null /* iconPath */, UserInfo.FLAG_QUIET_MODE,
+            UserManager.USER_TYPE_PROFILE_MANAGED);
     private static final int INVALID_STACK_ID = 999;
 
     private ActivityDisplay mDisplay;
@@ -125,7 +128,6 @@
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         mCallbacksRecorder = new CallbacksRecorder();
         mRecentTasks.registerCallback(mCallbacksRecorder);
-        QUIET_USER_INFO.flags = UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_QUIET_MODE;
 
         mTasks = new ArrayList<>();
         mTasks.add(createTaskBuilder(".Task1").build());
@@ -1220,7 +1222,7 @@
                 case TEST_USER_1_ID:
                     return DEFAULT_USER_INFO;
                 case TEST_QUIET_USER_ID:
-                    return QUIET_USER_INFO;
+                    return QUIET_PROFILE_USER_INFO;
             }
             return null;
         }
diff --git a/startop/apps/test/Android.bp b/startop/apps/test/Android.bp
index c7c70db..f42c755 100644
--- a/startop/apps/test/Android.bp
+++ b/startop/apps/test/Android.bp
@@ -17,6 +17,7 @@
 android_app {
     name: "startop_test_app",
     srcs: [
+        "src/ApplicationBenchmarks.java",
         "src/ComplexLayoutInflationActivity.java",
         "src/CPUIntensiveBenchmarkActivity.java",
         "src/CPUIntensiveBenchmarks.java",
diff --git a/startop/apps/test/src/ApplicationBenchmarks.java b/startop/apps/test/src/ApplicationBenchmarks.java
new file mode 100644
index 0000000..7d71916
--- /dev/null
+++ b/startop/apps/test/src/ApplicationBenchmarks.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.startop.test;
+
+import android.app.Activity;
+import android.view.LayoutInflater;
+
+final class ApplicationBenchmarks {
+
+    public static final void initializeBenchmarks(Activity parent, BenchmarkRunner benchmarks) {
+        LayoutInflater inflater = LayoutInflater.from(parent);
+
+        benchmarks.addBenchmark("Complex Layout", () -> {
+            inflater.inflate(R.layout.activity_main, null);
+        });
+
+        benchmarks.addBenchmark("TextView List Layout", () -> {
+            inflater.inflate(R.layout.textview_list, null);
+        });
+
+        benchmarks.addBenchmark("FrameLayout List Layout", () -> {
+            inflater.inflate(R.layout.framelayout_list, null);
+        });
+    }
+}
diff --git a/startop/apps/test/src/InteractiveMicrobenchmarkActivity.java b/startop/apps/test/src/InteractiveMicrobenchmarkActivity.java
index 8ed7f6a..c3839c1 100644
--- a/startop/apps/test/src/InteractiveMicrobenchmarkActivity.java
+++ b/startop/apps/test/src/InteractiveMicrobenchmarkActivity.java
@@ -36,6 +36,8 @@
         addBenchmark("Empty", () -> {
         });
         addHeader("Application Benchmarks");
+        ApplicationBenchmarks.initializeBenchmarks(this, this);
+        addHeader("CPU Intensive Benchmarks");
         CPUIntensiveBenchmarks.initializeBenchmarks(this, this);
         addHeader("Init Check Overhead Benchmarks");
         InitCheckOverheadBenchmarks.initializeBenchmarks(this, this);
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 3f95a81..89c4e90 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -514,7 +514,6 @@
             throw new IllegalArgumentException("Invalid message body");
         }
 
-        final Context context = ActivityThread.currentApplication().getApplicationContext();
         // We will only show the SMS disambiguation dialog in the case that the message is being
         // persisted. This is for two reasons:
         // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific
@@ -623,7 +622,6 @@
 
         final int finalPriority = priority;
         final int finalValidity = validityPeriod;
-        final Context context = ActivityThread.currentApplication().getApplicationContext();
         // We will only show the SMS disambiguation dialog in the case that the message is being
         // persisted. This is for two reasons:
         // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific
@@ -927,7 +925,6 @@
         }
 
         if (parts.size() > 1) {
-            final Context context = ActivityThread.currentApplication().getApplicationContext();
             // We will only show the SMS disambiguation dialog in the case that the message is being
             // persisted. This is for two reasons:
             // 1) Messages that are not persisted are sent by carrier/OEM apps for a specific
@@ -1168,7 +1165,6 @@
         if (parts.size() > 1) {
             final int finalPriority = priority;
             final int finalValidity = validityPeriod;
-            final Context context = ActivityThread.currentApplication().getApplicationContext();
             if (persistMessage) {
                 resolveSubscriptionForOperation(new SubscriptionResolverResult() {
                     @Override
@@ -1325,7 +1321,6 @@
             throw new IllegalArgumentException("Invalid message data");
         }
 
-        final Context context = ActivityThread.currentApplication().getApplicationContext();
         resolveSubscriptionForOperation(new SubscriptionResolverResult() {
             @Override
             public void onSuccess(int subId) {
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index f527bc3..9eff809 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -654,6 +654,7 @@
      * Return whether the subscription's group is disabled.
      * @hide
      */
+    @SystemApi
     public boolean isGroupDisabled() {
         return mIsGroupDisabled;
     }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 0d7a4f2..3d63e4a 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1286,12 +1286,32 @@
     }
 
     /**
-     * This is similar to {@link #getActiveSubscriptionInfoList()}, but if userVisibleOnly
-     * is true, it will filter out the hidden subscriptions.
+     * Get both hidden and visible SubscriptionInfo(s) of the currently active SIM(s).
+     * The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex}
+     * then by {@link SubscriptionInfo#getSubscriptionId}.
      *
-     * @hide
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see
+     * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible
+     * to the calling app are returned.
+     *
+     * @return Sorted list of the currently available {@link SubscriptionInfo}
+     * records on the device.
+     * This is similar to {@link #getActiveSubscriptionInfoList} except that it will return
+     * both active and hidden SubscriptionInfos.
+     *
      */
-    public List<SubscriptionInfo> getActiveSubscriptionInfoList(boolean userVisibleOnly) {
+    public @Nullable List<SubscriptionInfo> getActiveAndHiddenSubscriptionInfoList() {
+        return getActiveSubscriptionInfoList(/* userVisibleonly */false);
+    }
+
+    /**
+    * This is similar to {@link #getActiveSubscriptionInfoList()}, but if userVisibleOnly
+    * is true, it will filter out the hidden subscriptions.
+    *
+    * @hide
+    */
+    public @Nullable List<SubscriptionInfo> getActiveSubscriptionInfoList(boolean userVisibleOnly) {
         List<SubscriptionInfo> activeList = null;
 
         try {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0e08c6d..64b5aa5 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3574,13 +3574,36 @@
     }
 
     /**
+     * Returns the ISO-3166 country code equivalent for the SIM provider's country code
+     * of the default subscription
+     * <p>
+     * The ISO-3166 country code is provided in lowercase 2 character format.
+     * @return the lowercase 2 character ISO-3166 country code, or empty string is not available.
+     * <p>
+     * Note: This API is introduced to unblock mainlining work as the following APIs in
+     * Linkify.java invokes getSimCountryIso() without a context. TODO(Bug 144576376): remove
+     * this API once the following APIs are redesigned to access telephonymanager with a context.
+     *
+     * {@link Linkify#addLinks(@NonNull Spannable text, @LinkifyMask int mask)}
+     * {@link Linkify#addLinks(@NonNull Spannable text, @LinkifyMask int mask,
+               @Nullable Function<String, URLSpan> urlSpanFactory)}
+     *
+     * @hide
+     */
+    @SystemApi
+    @NonNull
+    public static String getDefaultSimCountryIso() {
+        return getSimCountryIso(SubscriptionManager.getDefaultSubscriptionId());
+    }
+
+    /**
      * Returns the ISO country code equivalent for the SIM provider's country code.
      *
      * @param subId for which SimCountryIso is returned
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
-    public String getSimCountryIso(int subId) {
+    public static String getSimCountryIso(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getSimCountryIsoForPhone(phoneId);
     }
@@ -3591,7 +3614,7 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public String getSimCountryIsoForPhone(int phoneId) {
+    public static String getSimCountryIsoForPhone(int phoneId) {
         return getTelephonyProperty(phoneId, TelephonyProperties.icc_operator_iso_country(), "");
     }
 
@@ -10839,6 +10862,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    @SystemApi
     public boolean setOpportunisticNetworkState(boolean enable) {
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         boolean ret = false;
@@ -10866,6 +10890,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @SystemApi
     public boolean isOpportunisticNetworkEnabled() {
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         boolean isEnabled = false;
@@ -11506,6 +11531,7 @@
      * @param slotIndex which slot it's checking.
      * @hide
      */
+    @SystemApi
     public boolean isModemEnabledForSlot(int slotIndex) {
         try {
             ITelephony telephony = getITelephony();
diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java
index 9d3e120..85e5916 100644
--- a/test-mock/src/android/test/mock/MockContentProvider.java
+++ b/test-mock/src/android/test/mock/MockContentProvider.java
@@ -71,8 +71,8 @@
 
         @Override
         public int delete(String callingPackage, @Nullable String featureId, Uri url,
-                String selection, String[] selectionArgs) throws RemoteException {
-            return MockContentProvider.this.delete(url, selection, selectionArgs);
+                Bundle extras) throws RemoteException {
+            return MockContentProvider.this.delete(url, extras);
         }
 
         @Override
@@ -82,8 +82,8 @@
 
         @Override
         public Uri insert(String callingPackage, @Nullable String featureId, Uri url,
-                ContentValues initialValues) throws RemoteException {
-            return MockContentProvider.this.insert(url, initialValues);
+                ContentValues initialValues, Bundle extras) throws RemoteException {
+            return MockContentProvider.this.insert(url, initialValues, extras);
         }
 
         @Override
@@ -109,9 +109,8 @@
 
         @Override
         public int update(String callingPackage, @Nullable String featureId, Uri url,
-                ContentValues values, String selection, String[] selectionArgs)
-                throws RemoteException {
-            return MockContentProvider.this.update(url, values, selection, selectionArgs);
+                ContentValues values, Bundle extras) throws RemoteException {
+            return MockContentProvider.this.update(url, values, extras);
         }
 
         @Override
diff --git a/test-mock/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java
index e512b52..464abfb 100644
--- a/test-mock/src/android/test/mock/MockIContentProvider.java
+++ b/test-mock/src/android/test/mock/MockIContentProvider.java
@@ -51,7 +51,7 @@
     @Override
     @SuppressWarnings("unused")
     public int delete(String callingPackage, @Nullable String featureId, Uri url,
-            String selection, String[] selectionArgs) throws RemoteException {
+            Bundle extras) throws RemoteException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
@@ -63,7 +63,7 @@
     @Override
     @SuppressWarnings("unused")
     public Uri insert(String callingPackage, @Nullable String featureId, Uri url,
-            ContentValues initialValues) throws RemoteException {
+            ContentValues initialValues, Bundle extras) throws RemoteException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
@@ -99,7 +99,7 @@
 
     @Override
     public int update(String callingPackage, @Nullable String featureId, Uri url,
-            ContentValues values, String selection, String[] selectionArgs) throws RemoteException {
+            ContentValues values, Bundle extras) throws RemoteException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp
deleted file mode 100644
index 5e9ef8e..0000000
--- a/tests/PlatformCompatGating/Android.bp
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-android_test {
-    name: "PlatformCompatGating",
-    // Only compile source java files in this apk.
-    srcs: ["src/**/*.java"],
-    certificate: "platform",
-    libs: [
-        "android.test.runner",
-        "android.test.base",
-    ],
-    static_libs: [
-        "junit",
-        "android-support-test",
-        "mockito-target-minus-junit4",
-        "truth-prebuilt",
-        "platform-compat-test-rules"
-    ],
-}
diff --git a/tests/PlatformCompatGating/AndroidManifest.xml b/tests/PlatformCompatGating/AndroidManifest.xml
deleted file mode 100644
index 7f14b83..0000000
--- a/tests/PlatformCompatGating/AndroidManifest.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.tests.gating">
-    <application android:label="GatingTest">
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="com.android.tests.gating"/>
-</manifest>
diff --git a/tests/PlatformCompatGating/AndroidTest.xml b/tests/PlatformCompatGating/AndroidTest.xml
deleted file mode 100644
index c626848..0000000
--- a/tests/PlatformCompatGating/AndroidTest.xml
+++ /dev/null
@@ -1,30 +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.
--->
-<configuration description="Test compatibility change gating.">
-    <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
-        <option name="test-file-name" value="PlatformCompatGating.apk"/>
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
-    <option name="test-suite-tag" value="apct"/>
-    <option name="test-tag" value="Gating"/>
-
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
-        <option name="package" value="com.android.tests.gating"/>
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
-        <option name="hidden-api-checks" value="false"/>
-    </test>
-</configuration>
diff --git a/tests/PlatformCompatGating/src/com/android/compat/testing/DummyApi.java b/tests/PlatformCompatGating/src/com/android/compat/testing/DummyApi.java
deleted file mode 100644
index 731be8e..0000000
--- a/tests/PlatformCompatGating/src/com/android/compat/testing/DummyApi.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.compat.testing;
-
-import android.compat.Compatibility;
-import android.content.Context;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-
-import com.android.internal.compat.IPlatformCompat;
-
-/**
- * This is a dummy API to test gating
- *
- * @hide
- */
-public class DummyApi {
-
-    public static final long CHANGE_ID = 666013;
-    public static final long CHANGE_ID_1 = 666014;
-    public static final long CHANGE_ID_2 = 666015;
-    public static final long CHANGE_SYSTEM_SERVER = 666016;
-
-    /**
-     * Dummy method
-     * @return "A" if change is enabled, "B" otherwise.
-     */
-    public static String dummyFunc() {
-        if (Compatibility.isChangeEnabled(CHANGE_ID)) {
-            return "A";
-        }
-        return "B";
-    }
-
-    /**
-     * Dummy combined method
-     * @return "0" if {@link CHANGE_ID_1} is disabled and {@link CHANGE_ID_2} is disabled,
-               "1" if {@link CHANGE_ID_1} is disabled and {@link CHANGE_ID_2} is enabled,
-               "2" if {@link CHANGE_ID_1} is enabled and {@link CHANGE_ID_2} is disabled,
-               "3" if {@link CHANGE_ID_1} is enabled and {@link CHANGE_ID_2} is enabled.
-     */
-    public static String dummyCombinedFunc() {
-        if (!Compatibility.isChangeEnabled(CHANGE_ID_1)
-                && !Compatibility.isChangeEnabled(CHANGE_ID_2)) {
-            return "0";
-        } else if (!Compatibility.isChangeEnabled(CHANGE_ID_1)
-                && Compatibility.isChangeEnabled(CHANGE_ID_2)) {
-            return "1";
-        } else if (Compatibility.isChangeEnabled(CHANGE_ID_1)
-                && !Compatibility.isChangeEnabled(CHANGE_ID_2)) {
-            return "2";
-        }
-        return "3";
-    }
-
-    /**
-     * Dummy api using system server API.
-     */
-    public static boolean dummySystemServer(Context context) {
-        IPlatformCompat platformCompat = IPlatformCompat.Stub
-                .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
-        if (platformCompat == null) {
-            throw new RuntimeException("Could not obtain IPlatformCompat instance!");
-        }
-        String packageName = context.getPackageName();
-        try {
-            return platformCompat.isChangeEnabledByPackageName(CHANGE_SYSTEM_SERVER, packageName,
-                                                            context.getUserId());
-        } catch (RemoteException e) {
-            throw new RuntimeException("Could not get change value!", e);
-        }
-    }
-}
diff --git a/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java
deleted file mode 100644
index dc317f19..0000000
--- a/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java
+++ /dev/null
@@ -1,94 +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 com.android.tests.gating;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.compat.testing.PlatformCompatChangeRule;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.compat.testing.DummyApi;
-
-import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
-import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestRule;
-import org.junit.runner.RunWith;
-
-/**
- * Tests for platform compatibility change gating.
- */
-@RunWith(AndroidJUnit4.class)
-public class PlatformCompatGatingTest {
-
-    @Rule
-    public TestRule compatChangeRule = new PlatformCompatChangeRule();
-
-    @Test
-    @EnableCompatChanges({DummyApi.CHANGE_ID})
-    public void testDummyGatingPositive() {
-        assertThat(DummyApi.dummyFunc()).isEqualTo("A");
-    }
-
-    @Test
-    @DisableCompatChanges({DummyApi.CHANGE_ID})
-    public void testDummyGatingNegative() {
-        assertThat(DummyApi.dummyFunc()).isEqualTo("B");
-    }
-
-    @Test
-    @DisableCompatChanges({DummyApi.CHANGE_ID_1, DummyApi.CHANGE_ID_2})
-    public void testDummyGatingCombined0() {
-        assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("0");
-    }
-
-    @Test
-    @DisableCompatChanges({DummyApi.CHANGE_ID_1})
-    @EnableCompatChanges({DummyApi.CHANGE_ID_2})
-    public void testDummyGatingCombined1() {
-        assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("1");
-    }
-
-    @Test
-    @EnableCompatChanges({DummyApi.CHANGE_ID_1})
-    @DisableCompatChanges({DummyApi.CHANGE_ID_2})
-    public void testDummyGatingCombined2() {
-        assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("2");
-    }
-
-    @Test
-    @EnableCompatChanges({DummyApi.CHANGE_ID_1, DummyApi.CHANGE_ID_2})
-    public void testDummyGatingCombined3() {
-        assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("3");
-    }
-
-    @Test
-    @EnableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER})
-    public void testDummyGatingPositiveSystemServer() {
-        assertThat(
-                DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isTrue();
-    }
-
-    @Test
-    @DisableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER})
-    public void testDummyGatingNegativeSystemServer() {
-        assertThat(
-                DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isFalse();
-    }
-}
diff --git a/tests/PlatformCompatGating/test-rules/Android.bp b/tests/PlatformCompatGating/test-rules/Android.bp
deleted file mode 100644
index 8211ef5..0000000
--- a/tests/PlatformCompatGating/test-rules/Android.bp
+++ /dev/null
@@ -1,26 +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.
-//
-
-java_library {
-    name: "platform-compat-test-rules",
-    srcs: ["src/**/*.java"],
-    static_libs: [
-        "junit",
-        "android-support-test",
-        "truth-prebuilt",
-        "core-compat-test-rules"
-    ],
-}
\ No newline at end of file
diff --git a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
deleted file mode 100644
index 4e61862..0000000
--- a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
+++ /dev/null
@@ -1,107 +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.compat.testing;
-
-import android.app.Instrumentation;
-import android.compat.Compatibility;
-import android.compat.Compatibility.ChangeConfig;
-import android.content.Context;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.support.test.InstrumentationRegistry;
-
-import com.android.internal.compat.CompatibilityChangeConfig;
-import com.android.internal.compat.IPlatformCompat;
-
-import libcore.junit.util.compat.CoreCompatChangeRule;
-
-import org.junit.runners.model.Statement;
-
-/**
- * Allows tests to specify the which change to disable.
- *
- * <p>To use add the following to the test class. It will only change the behavior of a test method
- * if it is annotated with
- * {@link libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges} and/or
- * {@link libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges}.
- * </p>
- * <pre>
- * @Rule
- * public TestRule compatChangeRule = new PlatformCompatChangeRule();
- * </pre>
- *
- * <p>Each test method that needs to disable a specific change needs to be annotated
- * with {@link libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges} and/or
- * {@link libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges} specifying the change
- * id. e.g.:
- * </p>
- * <pre>
- *   @Test
- *   @DisableCompatChanges({42})
- *   public void testAsIfChange42Disabled() {
- *     // check behavior
- *   }
- *
- *   @Test
- *   @EnableCompatChanges({42})
- *   public void testAsIfChange42Enabled() {
- *     // check behavior
- *
- * </pre>
- */
-public class PlatformCompatChangeRule extends CoreCompatChangeRule {
-
-    @Override
-    protected Statement createStatementForConfig(final Statement statement, ChangeConfig config) {
-        return new CompatChangeStatement(statement, config);
-    }
-
-
-    private static class CompatChangeStatement extends Statement {
-        private final Statement mTestStatement;
-        private final ChangeConfig mConfig;
-
-        private CompatChangeStatement(Statement testStatement, ChangeConfig config) {
-            this.mTestStatement = testStatement;
-            this.mConfig = config;
-        }
-
-        @Override
-        public void evaluate() throws Throwable {
-            Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-            String packageName = instrumentation.getTargetContext().getPackageName();
-            IPlatformCompat platformCompat = IPlatformCompat.Stub
-                    .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
-            if (platformCompat == null) {
-                throw new IllegalStateException("Could not get IPlatformCompat service!");
-            }
-            Compatibility.setOverrides(mConfig);
-            try {
-                platformCompat.setOverrides(new CompatibilityChangeConfig(mConfig), packageName);
-                try {
-                    mTestStatement.evaluate();
-                } finally {
-                    platformCompat.clearOverrides(packageName);
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException("Could not call IPlatformCompat binder method!", e);
-            } finally {
-                Compatibility.clearOverrides();
-            }
-        }
-    }
-}
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 5f62c08..9e5717b 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -208,6 +208,12 @@
             if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
             return super.getSystemService(name);
         }
+
+        @Override
+        public String getSystemServiceName(Class<?> serviceClass) {
+            if (TelephonyManager.class.equals(serviceClass)) return Context.TELEPHONY_SERVICE;
+            return super.getSystemServiceName(serviceClass);
+        }
     }
 
     public class MockIpServerDependencies extends IpServer.Dependencies {
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 1d29a82..4d42a61 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -192,8 +192,8 @@
 
         mService = new NetworkStatsService(
                 mServiceContext, mNetManager, mAlarmManager, wakeLock, mClock,
-                TelephonyManager.getDefault(), mSettings, mStatsFactory,
-                new NetworkStatsObservers(),  mStatsDir, getBaseDir(mStatsDir));
+                mServiceContext.getSystemService(TelephonyManager.class), mSettings,
+                mStatsFactory, new NetworkStatsObservers(),  mStatsDir, getBaseDir(mStatsDir));
         mHandlerThread = new HandlerThread("HandlerThread");
         mHandlerThread.start();
         Handler.Callback callback = new NetworkStatsService.HandlerCallback(mService);
diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py
index e883c6b..46105f4 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -241,8 +241,6 @@
             flags = csv[1:]
             if (FLAG_PUBLIC_API in flags) or (FLAG_SYSTEM_API in flags):
                 flags.append(FLAG_WHITELIST)
-            elif FLAG_TEST_API in flags:
-                flags.append(FLAG_GREYLIST)
             self._dict[csv[0]].update(flags)
 
     def assign_flag(self, flag, apis, source="<unknown>"):
diff --git a/tools/hiddenapi/generate_hiddenapi_lists_test.py b/tools/hiddenapi/generate_hiddenapi_lists_test.py
index 4dc880b..55c3a7d 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists_test.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists_test.py
@@ -53,14 +53,22 @@
         # Test new additions.
         flags.parse_and_merge_csv([
             'A,' + FLAG_GREYLIST,
-            'B,' + FLAG_BLACKLIST + ',' + FLAG_GREYLIST_MAX_O ])
-        self.assertEqual(flags.generate_csv(),
-            [ 'A,' + FLAG_GREYLIST,
-              'B,' + FLAG_BLACKLIST + "," + FLAG_GREYLIST_MAX_O ])
+            'B,' + FLAG_BLACKLIST + ',' + FLAG_GREYLIST_MAX_O,
+            'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST,
+            'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API,
+            'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API,
+        ])
+        self.assertEqual(flags.generate_csv(), [
+            'A,' + FLAG_GREYLIST,
+            'B,' + FLAG_BLACKLIST + "," + FLAG_GREYLIST_MAX_O,
+            'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST,
+            'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API,
+            'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API,
+        ])
 
         # Test unknown flag.
         with self.assertRaises(AssertionError):
-            flags.parse_and_merge_csv([ 'C,foo' ])
+            flags.parse_and_merge_csv([ 'Z,foo' ])
 
     def test_assign_flag(self):
         flags = FlagsDict()