Merge "Add metrics for DevicePolicyManagerService methods (Part 1)"
diff --git a/Android.bp b/Android.bp
index 34162d1..5568673 100644
--- a/Android.bp
+++ b/Android.bp
@@ -268,6 +268,8 @@
         "core/java/android/rolecontrollerservice/IRoleControllerService.aidl",
         ":keystore_aidl",
         "core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl",
+        "core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl",
+        "core/java/android/service/autofill/augmented/IFillCallback.aidl",
         "core/java/android/service/autofill/IAutoFillService.aidl",
         "core/java/android/service/autofill/IAutofillFieldClassificationService.aidl",
         "core/java/android/service/autofill/IFillCallback.aidl",
@@ -290,7 +292,7 @@
         "core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl",
         "core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl",
         "core/java/android/service/gatekeeper/IGateKeeperService.aidl",
-        "core/java/android/service/intelligence/IIntelligenceService.aidl",
+        "core/java/android/service/contentcapture/IContentCaptureService.aidl",
         "core/java/android/service/notification/INotificationListener.aidl",
         "core/java/android/service/notification/IStatusBarNotificationHolder.aidl",
         "core/java/android/service/notification/IConditionListener.aidl",
@@ -351,7 +353,7 @@
         "core/java/android/view/autofill/IAutoFillManagerClient.aidl",
         "core/java/android/view/autofill/IAugmentedAutofillManagerClient.aidl",
         "core/java/android/view/autofill/IAutofillWindowPresenter.aidl",
-        "core/java/android/view/intelligence/IIntelligenceManager.aidl",
+        "core/java/android/view/contentcapture/IContentCaptureManager.aidl",
         "core/java/android/view/IApplicationToken.aidl",
         "core/java/android/view/IAppTransitionAnimationSpecsFuture.aidl",
         "core/java/android/view/IDockedStackListener.aidl",
@@ -631,7 +633,6 @@
         ":libupdate_engine_aidl",
 
         ":storaged_aidl",
-        ":netd_aidl",
         ":vold_aidl",
         ":installd_aidl",
         ":dumpstate_aidl",
@@ -1615,6 +1616,7 @@
     ],
     dex_mapping_filename: "dex-mapping.txt",
     args: metalava_framework_docs_args +
+        " --hide ReferencesHidden " +
         " --show-unannotated " +
         " --show-annotation android.annotation.SystemApi " +
         " --show-annotation android.annotation.TestApi "
diff --git a/api/current.txt b/api/current.txt
index e65220b..fe91ba1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6664,7 +6664,7 @@
     method public void setDelegatedScopes(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>);
     method public void setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.CharSequence);
     method public void setEndUserSessionMessage(android.content.ComponentName, java.lang.CharSequence);
-    method public void setGlobalPrivateDns(android.content.ComponentName, int, java.lang.String);
+    method public int setGlobalPrivateDns(android.content.ComponentName, int, java.lang.String);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public void setKeepUninstalledPackages(android.content.ComponentName, java.util.List<java.lang.String>);
     method public boolean setKeyPairCertificate(android.content.ComponentName, java.lang.String, java.util.List<java.security.cert.Certificate>, boolean);
@@ -6845,6 +6845,9 @@
     field public static final int PRIVATE_DNS_MODE_OPPORTUNISTIC = 2; // 0x2
     field public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = 3; // 0x3
     field public static final int PRIVATE_DNS_MODE_UNKNOWN = 0; // 0x0
+    field public static final int PRIVATE_DNS_SET_ERROR_FAILURE_SETTING = 2; // 0x2
+    field public static final int PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING = 1; // 0x1
+    field public static final int PRIVATE_DNS_SET_SUCCESS = 0; // 0x0
     field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
     field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
     field public static final int SKIP_SETUP_WIZARD = 1; // 0x1
@@ -9227,11 +9230,31 @@
     field public static final android.os.Parcelable.Creator<android.content.ComponentName> CREATOR;
   }
 
-  public abstract class ContentProvider implements android.content.ComponentCallbacks2 {
+  public abstract interface ContentInterface {
+    method public abstract android.content.ContentProviderResult[] applyBatch(java.lang.String, java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
+    method public abstract int bulkInsert(android.net.Uri, android.content.ContentValues[]) throws android.os.RemoteException;
+    method public abstract android.os.Bundle call(java.lang.String, java.lang.String, java.lang.String, android.os.Bundle) throws android.os.RemoteException;
+    method public abstract android.net.Uri canonicalize(android.net.Uri) throws android.os.RemoteException;
+    method public abstract int delete(android.net.Uri, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
+    method public abstract java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String) throws android.os.RemoteException;
+    method public abstract java.lang.String getType(android.net.Uri) throws android.os.RemoteException;
+    method public abstract android.net.Uri insert(android.net.Uri, android.content.ContentValues) throws android.os.RemoteException;
+    method public abstract android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
+    method public abstract android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
+    method public abstract android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
+    method public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal) throws android.os.RemoteException;
+    method public abstract boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal) throws android.os.RemoteException;
+    method public abstract android.net.Uri uncanonicalize(android.net.Uri) throws android.os.RemoteException;
+    method public abstract int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
+  }
+
+  public abstract class ContentProvider implements android.content.ComponentCallbacks2 android.content.ContentInterface {
     ctor public ContentProvider();
+    method public android.content.ContentProviderResult[] applyBatch(java.lang.String, java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException;
     method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException;
     method public void attachInfo(android.content.Context, android.content.pm.ProviderInfo);
     method public int bulkInsert(android.net.Uri, android.content.ContentValues[]);
+    method public android.os.Bundle call(java.lang.String, java.lang.String, java.lang.String, android.os.Bundle);
     method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle);
     method public android.net.Uri canonicalize(android.net.Uri);
     method public final android.content.ContentProvider.CallingIdentity clearCallingIdentity();
@@ -9278,10 +9301,12 @@
     method public abstract void writeDataToPipe(android.os.ParcelFileDescriptor, android.net.Uri, java.lang.String, android.os.Bundle, T);
   }
 
-  public class ContentProviderClient implements java.lang.AutoCloseable {
+  public class ContentProviderClient implements java.lang.AutoCloseable android.content.ContentInterface {
     method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
+    method public android.content.ContentProviderResult[] applyBatch(java.lang.String, java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
     method public int bulkInsert(android.net.Uri, android.content.ContentValues[]) throws android.os.RemoteException;
     method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle) throws android.os.RemoteException;
+    method public android.os.Bundle call(java.lang.String, java.lang.String, java.lang.String, android.os.Bundle) throws android.os.RemoteException;
     method public final android.net.Uri canonicalize(android.net.Uri) throws android.os.RemoteException;
     method public void close();
     method public static void closeQuietly(android.content.ContentProviderClient);
@@ -9294,6 +9319,7 @@
     method public android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
     method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException, android.os.RemoteException;
     method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
+    method public final android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
     method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException, android.os.RemoteException;
     method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
     method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String) throws android.os.RemoteException;
@@ -9358,7 +9384,7 @@
     method public void setKeepUpdated(boolean);
   }
 
-  public abstract class ContentResolver {
+  public abstract class ContentResolver implements android.content.ContentInterface {
     ctor public ContentResolver(android.content.Context);
     method public final android.content.ContentProviderClient acquireContentProviderClient(android.net.Uri);
     method public final android.content.ContentProviderClient acquireContentProviderClient(java.lang.String);
@@ -9369,6 +9395,7 @@
     method public android.content.ContentProviderResult[] applyBatch(java.lang.String, java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
     method public final int bulkInsert(android.net.Uri, android.content.ContentValues[]);
     method public final android.os.Bundle call(android.net.Uri, java.lang.String, java.lang.String, android.os.Bundle);
+    method public final android.os.Bundle call(java.lang.String, java.lang.String, java.lang.String, android.os.Bundle);
     method public deprecated void cancelSync(android.net.Uri);
     method public static void cancelSync(android.accounts.Account, java.lang.String);
     method public static void cancelSync(android.content.SyncRequest);
@@ -9392,13 +9419,16 @@
     method public void notifyChange(android.net.Uri, android.database.ContentObserver);
     method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
     method public void notifyChange(android.net.Uri, android.database.ContentObserver, int);
+    method public final android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
     method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
+    method public final android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
     method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public final java.io.InputStream openInputStream(android.net.Uri) throws java.io.FileNotFoundException;
     method public final java.io.OutputStream openOutputStream(android.net.Uri) throws java.io.FileNotFoundException;
     method public final java.io.OutputStream openOutputStream(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
+    method public final android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException;
     method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
@@ -11479,6 +11509,7 @@
     field public static final java.lang.String FEATURE_HIFI_SENSORS = "android.hardware.sensor.hifi_sensors";
     field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
     field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
+    field public static final java.lang.String FEATURE_IPSEC_TUNNELS = "android.software.ipsec_tunnels";
     field public static final java.lang.String FEATURE_IRIS = "android.hardware.iris";
     field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
     field public static final java.lang.String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
@@ -27019,6 +27050,7 @@
 
   public static final class MediaSessionManager.RemoteUserInfo {
     ctor public MediaSessionManager.RemoteUserInfo(java.lang.String, int, int);
+    ctor public MediaSessionManager.RemoteUserInfo(java.lang.String, int, int, android.os.IBinder);
     method public java.lang.String getPackageName();
     method public int getPid();
     method public int getUid();
@@ -28339,6 +28371,7 @@
     method public int describeContents();
     method public int getLinkDownstreamBandwidthKbps();
     method public int getLinkUpstreamBandwidthKbps();
+    method public android.net.TransportInfo getTransportInfo();
     method public boolean hasCapability(int);
     method public boolean hasTransport(int);
     method public void writeToParcel(android.os.Parcel, int);
@@ -28547,6 +28580,9 @@
     field public static final int UNSUPPORTED = -1; // 0xffffffff
   }
 
+  public abstract interface TransportInfo {
+  }
+
   public abstract class Uri implements java.lang.Comparable android.os.Parcelable {
     method public abstract android.net.Uri.Builder buildUpon();
     method public int compareTo(android.net.Uri);
@@ -28582,6 +28618,7 @@
     method public abstract boolean isRelative();
     method public android.net.Uri normalizeScheme();
     method public static android.net.Uri parse(java.lang.String);
+    method public java.lang.String toSafeString();
     method public abstract java.lang.String toString();
     method public static android.net.Uri withAppendedPath(android.net.Uri, java.lang.String);
     method public static void writeToParcel(android.os.Parcel, android.net.Uri);
@@ -34659,6 +34696,7 @@
     field public static final java.lang.String DISALLOW_CONFIG_TETHERING = "no_config_tethering";
     field public static final java.lang.String DISALLOW_CONFIG_VPN = "no_config_vpn";
     field public static final java.lang.String DISALLOW_CONFIG_WIFI = "no_config_wifi";
+    field public static final java.lang.String DISALLOW_CONTENT_CAPTURE = "no_content_capture";
     field public static final java.lang.String DISALLOW_CREATE_WINDOWS = "no_create_windows";
     field public static final java.lang.String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste";
     field public static final java.lang.String DISALLOW_DATA_ROAMING = "no_data_roaming";
@@ -34668,7 +34706,6 @@
     field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps";
     field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
     field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY = "no_install_unknown_sources_globally";
-    field public static final java.lang.String DISALLOW_INTELLIGENCE_CAPTURE = "no_intelligence_capture";
     field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
     field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
     field public static final java.lang.String DISALLOW_NETWORK_RESET = "no_network_reset";
@@ -35998,6 +36035,7 @@
     field public static final java.lang.String CALENDAR_LOCATION = "calendar_location";
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String DEFAULT_SORT_ORDER = "calendar_displayName";
+    field public static final android.net.Uri ENTERPRISE_CONTENT_URI;
     field public static final java.lang.String NAME = "name";
   }
 
@@ -36026,6 +36064,7 @@
   public static final class CalendarContract.Events implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.SyncColumns {
     field public static final android.net.Uri CONTENT_EXCEPTION_URI;
     field public static final android.net.Uri CONTENT_URI;
+    field public static final android.net.Uri ENTERPRISE_CONTENT_URI;
   }
 
   protected static abstract interface CalendarContract.EventsColumns {
@@ -36117,6 +36156,10 @@
     field public static final java.lang.String END = "end";
     field public static final java.lang.String END_DAY = "endDay";
     field public static final java.lang.String END_MINUTE = "endMinute";
+    field public static final android.net.Uri ENTERPRISE_CONTENT_BY_DAY_URI;
+    field public static final android.net.Uri ENTERPRISE_CONTENT_SEARCH_BY_DAY_URI;
+    field public static final android.net.Uri ENTERPRISE_CONTENT_SEARCH_URI;
+    field public static final android.net.Uri ENTERPRISE_CONTENT_URI;
     field public static final java.lang.String EVENT_ID = "event_id";
     field public static final java.lang.String START_DAY = "startDay";
     field public static final java.lang.String START_MINUTE = "startMinute";
@@ -37362,22 +37405,26 @@
     method public static android.net.Uri buildRootsUri(java.lang.String);
     method public static android.net.Uri buildSearchDocumentsUri(java.lang.String, java.lang.String, java.lang.String);
     method public static android.net.Uri buildTreeDocumentUri(java.lang.String, java.lang.String);
-    method public static android.net.Uri copyDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
-    method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
-    method public static android.content.IntentSender createWebLinkIntent(android.content.ContentResolver, android.net.Uri, android.os.Bundle) throws java.io.FileNotFoundException;
-    method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException;
-    method public static void ejectRoot(android.content.ContentResolver, android.net.Uri);
-    method public static android.provider.DocumentsContract.Path findDocumentPath(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException;
+    method public static android.net.Uri copyDocument(android.content.ContentInterface, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
+    method public static android.net.Uri createDocument(android.content.ContentInterface, android.net.Uri, java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
+    method public static android.content.IntentSender createWebLinkIntent(android.content.ContentInterface, android.net.Uri, android.os.Bundle) throws java.io.FileNotFoundException;
+    method public static boolean deleteDocument(android.content.ContentInterface, android.net.Uri) throws java.io.FileNotFoundException;
+    method public static void ejectRoot(android.content.ContentInterface, android.net.Uri);
+    method public static android.provider.DocumentsContract.Path findDocumentPath(android.content.ContentInterface, android.net.Uri) throws java.io.FileNotFoundException;
     method public static java.lang.String getDocumentId(android.net.Uri);
-    method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal) throws java.io.FileNotFoundException;
+    method public static android.os.Bundle getDocumentMetadata(android.content.ContentInterface, android.net.Uri) throws java.io.FileNotFoundException;
+    method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentInterface, android.net.Uri, android.graphics.Point, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public static java.lang.String getRootId(android.net.Uri);
     method public static java.lang.String getSearchDocumentsQuery(android.net.Uri);
     method public static java.lang.String getTreeDocumentId(android.net.Uri);
+    method public static boolean isChildDocument(android.content.ContentInterface, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
     method public static boolean isDocumentUri(android.content.Context, android.net.Uri);
+    method public static boolean isRootUri(android.content.Context, android.net.Uri);
+    method public static boolean isRootsUri(android.content.Context, android.net.Uri);
     method public static boolean isTreeUri(android.net.Uri);
-    method public static android.net.Uri moveDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
-    method public static boolean removeDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
-    method public static android.net.Uri renameDocument(android.content.ContentResolver, android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
+    method public static android.net.Uri moveDocument(android.content.ContentInterface, android.net.Uri, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
+    method public static boolean removeDocument(android.content.ContentInterface, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
+    method public static android.net.Uri renameDocument(android.content.ContentInterface, android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
     field public static final java.lang.String ACTION_DOCUMENT_SETTINGS = "android.provider.action.DOCUMENT_SETTINGS";
     field public static final java.lang.String EXTRA_ERROR = "error";
     field public static final java.lang.String EXTRA_EXCLUDE_SELF = "android.provider.extra.EXCLUDE_SELF";
@@ -37386,7 +37433,14 @@
     field public static final java.lang.String EXTRA_LOADING = "loading";
     field public static final java.lang.String EXTRA_ORIENTATION = "android.provider.extra.ORIENTATION";
     field public static final java.lang.String EXTRA_PROMPT = "android.provider.extra.PROMPT";
+    field public static final java.lang.String METADATA_EXIF = "android:documentExif";
+    field public static final java.lang.String METADATA_TYPES = "android:documentMetadataTypes";
     field public static final java.lang.String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER";
+    field public static final java.lang.String QUERY_ARG_DISPLAY_NAME = "android:query-arg-display-name";
+    field public static final java.lang.String QUERY_ARG_EXCLUDE_MEDIA = "android:query-arg-exclude-media";
+    field public static final java.lang.String QUERY_ARG_FILE_SIZE_OVER = "android:query-arg-file-size-over";
+    field public static final java.lang.String QUERY_ARG_LAST_MODIFIED_AFTER = "android:query-arg-last-modified-after";
+    field public static final java.lang.String QUERY_ARG_MIME_TYPES = "android:query-arg-mime-types";
   }
 
   public static final class DocumentsContract.Document {
@@ -37401,8 +37455,10 @@
     field public static final int FLAG_DIR_PREFERS_GRID = 16; // 0x10
     field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 32; // 0x20
     field public static final int FLAG_DIR_SUPPORTS_CREATE = 8; // 0x8
+    field public static final int FLAG_PARTIAL = 8192; // 0x2000
     field public static final int FLAG_SUPPORTS_COPY = 128; // 0x80
     field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4
+    field public static final int FLAG_SUPPORTS_METADATA = 16384; // 0x4000
     field public static final int FLAG_SUPPORTS_MOVE = 256; // 0x100
     field public static final int FLAG_SUPPORTS_REMOVE = 1024; // 0x400
     field public static final int FLAG_SUPPORTS_RENAME = 64; // 0x40
@@ -37433,6 +37489,7 @@
     field public static final java.lang.String COLUMN_ROOT_ID = "root_id";
     field public static final java.lang.String COLUMN_SUMMARY = "summary";
     field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final int FLAG_EMPTY = 64; // 0x40
     field public static final int FLAG_LOCAL_ONLY = 2; // 0x2
     field public static final int FLAG_SUPPORTS_CREATE = 1; // 0x1
     field public static final int FLAG_SUPPORTS_EJECT = 32; // 0x20
@@ -37451,6 +37508,7 @@
     method public void deleteDocument(java.lang.String) throws java.io.FileNotFoundException;
     method public void ejectRoot(java.lang.String);
     method public android.provider.DocumentsContract.Path findDocumentPath(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
+    method public android.os.Bundle getDocumentMetadata(java.lang.String) throws java.io.FileNotFoundException;
     method public java.lang.String[] getDocumentStreamTypes(java.lang.String, java.lang.String);
     method public java.lang.String getDocumentType(java.lang.String) throws java.io.FileNotFoundException;
     method public final java.lang.String getType(android.net.Uri);
@@ -37475,6 +37533,7 @@
     method public android.database.Cursor queryRecentDocuments(java.lang.String, java.lang.String[], android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public abstract android.database.Cursor queryRoots(java.lang.String[]) throws java.io.FileNotFoundException;
     method public android.database.Cursor querySearchDocuments(java.lang.String, java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
+    method public android.database.Cursor querySearchDocuments(java.lang.String, java.lang.String[], android.os.Bundle) throws java.io.FileNotFoundException;
     method public void removeDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public java.lang.String renameDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public final void revokeDocumentPermission(java.lang.String);
@@ -51850,6 +51909,21 @@
 
 }
 
+package android.view.contentcapture {
+
+  public final class ContentCaptureManager {
+    method public android.content.ComponentName getServiceComponentName();
+    method public boolean isContentCaptureEnabled();
+    method public android.view.ViewStructure newVirtualViewStructure(android.view.autofill.AutofillId, int);
+    method public void notifyViewAppeared(android.view.ViewStructure);
+    method public void notifyViewDisappeared(android.view.autofill.AutofillId);
+    method public void notifyViewTextChanged(android.view.autofill.AutofillId, java.lang.CharSequence, int);
+    method public void setContentCaptureEnabled(boolean);
+    field public static final int FLAG_USER_INPUT = 1; // 0x1
+  }
+
+}
+
 package android.view.inputmethod {
 
   public class BaseInputConnection implements android.view.inputmethod.InputConnection {
@@ -52331,21 +52405,6 @@
 
 }
 
-package android.view.intelligence {
-
-  public final class ContentCaptureManager {
-    method public android.content.ComponentName getServiceComponentName();
-    method public boolean isContentCaptureEnabled();
-    method public android.view.ViewStructure newVirtualViewStructure(android.view.autofill.AutofillId, int);
-    method public void notifyViewAppeared(android.view.ViewStructure);
-    method public void notifyViewDisappeared(android.view.autofill.AutofillId);
-    method public void notifyViewTextChanged(android.view.autofill.AutofillId, java.lang.CharSequence, int);
-    method public void setContentCaptureEnabled(boolean);
-    field public static final int FLAG_USER_INPUT = 1; // 0x1
-  }
-
-}
-
 package android.view.textclassifier {
 
   public final class ConversationActions implements android.os.Parcelable {
@@ -53234,6 +53293,7 @@
     method public abstract boolean getDomStorageEnabled();
     method public abstract java.lang.String getFantasyFontFamily();
     method public abstract java.lang.String getFixedFontFamily();
+    method public int getForceDarkMode();
     method public abstract boolean getJavaScriptCanOpenWindowsAutomatically();
     method public abstract boolean getJavaScriptEnabled();
     method public abstract android.webkit.WebSettings.LayoutAlgorithm getLayoutAlgorithm();
@@ -53280,6 +53340,7 @@
     method public abstract deprecated void setEnableSmoothTransition(boolean);
     method public abstract void setFantasyFontFamily(java.lang.String);
     method public abstract void setFixedFontFamily(java.lang.String);
+    method public void setForceDarkMode(int);
     method public abstract deprecated void setGeolocationDatabasePath(java.lang.String);
     method public abstract void setGeolocationEnabled(boolean);
     method public abstract void setJavaScriptCanOpenWindowsAutomatically(boolean);
@@ -53310,6 +53371,9 @@
     method public abstract void setUserAgentString(java.lang.String);
     method public abstract boolean supportMultipleWindows();
     method public abstract boolean supportZoom();
+    field public static final int FORCE_DARK_AUTO = 0; // 0x0
+    field public static final int FORCE_DARK_OFF = -1; // 0xffffffff
+    field public static final int FORCE_DARK_ON = 1; // 0x1
     field public static final int LOAD_CACHE_ELSE_NETWORK = 1; // 0x1
     field public static final int LOAD_CACHE_ONLY = 3; // 0x3
     field public static final int LOAD_DEFAULT = -1; // 0xffffffff
diff --git a/api/system-current.txt b/api/system-current.txt
index 9cf66b2..f4eb2e9 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -21,7 +21,9 @@
     field public static final java.lang.String BACKUP = "android.permission.BACKUP";
     field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
     field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
+    field public static final java.lang.String BIND_AUGMENTED_AUTOFILL_SERVICE = "android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE";
     field public static final deprecated java.lang.String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE";
+    field public static final java.lang.String BIND_CONTENT_CAPTURE_SERVICE = "android.permission.BIND_CONTENT_CAPTURE_SERVICE";
     field public static final java.lang.String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH";
     field public static final java.lang.String BIND_EUICC_SERVICE = "android.permission.BIND_EUICC_SERVICE";
     field public static final java.lang.String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE";
@@ -33,7 +35,6 @@
     field public static final java.lang.String BIND_RESOLVER_RANKER_SERVICE = "android.permission.BIND_RESOLVER_RANKER_SERVICE";
     field public static final java.lang.String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE";
     field public static final java.lang.String BIND_SETTINGS_SUGGESTIONS_SERVICE = "android.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE";
-    field public static final java.lang.String BIND_SMART_SUGGESTIONS_SERVICE = "android.permission.BIND_SMART_SUGGESTIONS_SERVICE";
     field public static final java.lang.String BIND_SOUND_TRIGGER_DETECTION_SERVICE = "android.permission.BIND_SOUND_TRIGGER_DETECTION_SERVICE";
     field public static final java.lang.String BIND_TELEPHONY_DATA_SERVICE = "android.permission.BIND_TELEPHONY_DATA_SERVICE";
     field public static final java.lang.String BIND_TELEPHONY_NETWORK_SERVICE = "android.permission.BIND_TELEPHONY_NETWORK_SERVICE";
@@ -105,11 +106,11 @@
     field public static final java.lang.String MANAGE_AUTO_FILL = "android.permission.MANAGE_AUTO_FILL";
     field public static final java.lang.String MANAGE_CARRIER_OEM_UNLOCK_STATE = "android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE";
     field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
+    field public static final java.lang.String MANAGE_CONTENT_CAPTURE = "android.permission.MANAGE_CONTENT_CAPTURE";
     field public static final java.lang.String MANAGE_DEBUGGING = "android.permission.MANAGE_DEBUGGING";
     field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
     field public static final java.lang.String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
     field public static final java.lang.String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
-    field public static final java.lang.String MANAGE_SMART_SUGGESTIONS = "android.permission.MANAGE_SMART_SUGGESTIONS";
     field public static final java.lang.String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER";
     field public static final java.lang.String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS";
     field public static final java.lang.String MANAGE_USB = "android.permission.MANAGE_USB";
@@ -613,7 +614,12 @@
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL";
     field public static final java.lang.String EXTRA_PROVISIONING_ORGANIZATION_NAME = "android.app.extra.PROVISIONING_ORGANIZATION_NAME";
     field public static final java.lang.String EXTRA_PROVISIONING_SUPPORT_URL = "android.app.extra.PROVISIONING_SUPPORT_URL";
+    field public static final java.lang.String EXTRA_PROVISIONING_TRIGGER = "android.app.extra.PROVISIONING_TRIGGER";
     field public static final java.lang.String EXTRA_RESTRICTION = "android.app.extra.RESTRICTION";
+    field public static final int PROVISIONING_TRIGGER_CLOUD_ENROLLMENT = 1; // 0x1
+    field public static final int PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER = 3; // 0x3
+    field public static final int PROVISIONING_TRIGGER_QR_CODE = 2; // 0x2
+    field public static final int PROVISIONING_TRIGGER_UNSPECIFIED = 0; // 0x0
     field public static final int STATE_USER_PROFILE_COMPLETE = 4; // 0x4
     field public static final int STATE_USER_SETUP_COMPLETE = 2; // 0x2
     field public static final int STATE_USER_SETUP_FINALIZED = 3; // 0x3
@@ -844,6 +850,8 @@
     method public int restoreAll(long, android.app.backup.RestoreObserver);
     method public int restorePackage(java.lang.String, android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor);
     method public int restorePackage(java.lang.String, android.app.backup.RestoreObserver);
+    method public int restoreSome(long, android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor, java.lang.String[]);
+    method public int restoreSome(long, android.app.backup.RestoreObserver, java.lang.String[]);
   }
 
   public class RestoreSet implements android.os.Parcelable {
@@ -1030,6 +1038,10 @@
 
 package android.content {
 
+  public class ContentProviderClient implements java.lang.AutoCloseable android.content.ContentInterface {
+    method public void setDetectNotResponding(long);
+  }
+
   public abstract class Context {
     method public boolean bindServiceAsUser(android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle);
     method public abstract android.content.Context createCredentialProtectedStorageContext();
@@ -2919,6 +2931,13 @@
     field public static final int RADIO_TUNER = 1998; // 0x7ce
   }
 
+  public static class MediaTimestamp.Builder {
+    ctor public MediaTimestamp.Builder();
+    ctor public MediaTimestamp.Builder(android.media.MediaTimestamp);
+    method public android.media.MediaTimestamp build();
+    method public android.media.MediaTimestamp.Builder setMediaTimestamp(long, long, float);
+  }
+
   public class PlayerProxy {
     method public void pause();
     method public void setPan(float);
@@ -2939,7 +2958,7 @@
     ctor public TimedMetaData.Builder();
     ctor public TimedMetaData.Builder(android.media.TimedMetaData);
     method public android.media.TimedMetaData build();
-    method public android.media.TimedMetaData.Builder setTimedMetaData(int, byte[]);
+    method public android.media.TimedMetaData.Builder setTimedMetaData(long, byte[]);
   }
 
 }
@@ -3029,7 +3048,6 @@
 package android.media.session {
 
   public final class MediaSessionManager {
-    method public android.media.session.ISession createSession(android.media.session.MediaSession.CallbackStub, java.lang.String, int);
     method public void setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, android.os.Handler);
     method public void setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager.OnVolumeKeyLongPressListener, android.os.Handler);
   }
@@ -4317,6 +4335,7 @@
   }
 
   public class UserManager {
+    method public boolean canSwitchUsers();
     method public void clearSeedAccountData();
     method public android.os.UserHandle getProfileParent(android.os.UserHandle);
     method public java.lang.String getSeedAccountName();
@@ -4332,6 +4351,7 @@
     method public boolean isManagedProfile(int);
     method public boolean isPrimaryUser();
     method public boolean isRestrictedProfile();
+    method public boolean removeUser(android.os.UserHandle);
     field public static final java.lang.String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
     field public static final deprecated java.lang.String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
     field public static final java.lang.String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
@@ -4506,6 +4526,26 @@
     field public static final java.lang.String STATE = "state";
   }
 
+  public final class DocumentsContract {
+    method public static boolean isManageMode(android.net.Uri);
+    method public static android.net.Uri setManageMode(android.net.Uri);
+    field public static final java.lang.String ACTION_DOCUMENT_ROOT_SETTINGS = "android.provider.action.DOCUMENT_ROOT_SETTINGS";
+    field public static final java.lang.String ACTION_MANAGE_DOCUMENT = "android.provider.action.MANAGE_DOCUMENT";
+    field public static final java.lang.String EXTRA_SHOW_ADVANCED = "android.provider.extra.SHOW_ADVANCED";
+  }
+
+  public static final class DocumentsContract.Root {
+    field public static final int FLAG_ADVANCED = 65536; // 0x10000
+    field public static final int FLAG_HAS_SETTINGS = 131072; // 0x20000
+    field public static final int FLAG_REMOVABLE_SD = 262144; // 0x40000
+    field public static final int FLAG_REMOVABLE_USB = 524288; // 0x80000
+  }
+
+  public final class MediaStore {
+    method public static void deleteContributedMedia(android.content.Context, java.lang.String);
+    method public static long getContributedMediaSize(android.content.Context, java.lang.String);
+  }
+
   public abstract class SearchIndexableData {
     ctor public SearchIndexableData();
     ctor public SearchIndexableData(android.content.Context);
@@ -4858,6 +4898,69 @@
 
 }
 
+package android.service.autofill.augmented {
+
+  public abstract class AugmentedAutofillService extends android.app.Service {
+    ctor public AugmentedAutofillService();
+    method public void onFillRequest(android.service.autofill.augmented.FillRequest, android.os.CancellationSignal, android.service.autofill.augmented.FillController, android.service.autofill.augmented.FillCallback);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.augmented.AugmentedAutofillService";
+  }
+
+  public final class FillCallback {
+    method public void onSuccess(android.service.autofill.augmented.FillResponse);
+  }
+
+  public final class FillController {
+    method public void autofill(java.util.List<android.util.Pair<android.view.autofill.AutofillId, android.view.autofill.AutofillValue>>);
+  }
+
+  public final class FillRequest {
+    method public android.content.ComponentName getActivityComponent();
+    method public android.view.autofill.AutofillId getFocusedId();
+    method public android.view.autofill.AutofillValue getFocusedValue();
+    method public android.service.autofill.augmented.PresentationParams getPresentationParams();
+    method public int getTaskId();
+  }
+
+  public final class FillResponse implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.augmented.FillResponse> CREATOR;
+  }
+
+  public static final class FillResponse.Builder {
+    ctor public FillResponse.Builder();
+    method public android.service.autofill.augmented.FillResponse build();
+    method public android.service.autofill.augmented.FillResponse.Builder setFillWindow(android.service.autofill.augmented.FillWindow);
+    method public android.service.autofill.augmented.FillResponse.Builder setIgnoredIds(java.util.List<android.view.autofill.AutofillId>);
+  }
+
+  public final class FillWindow implements java.lang.AutoCloseable {
+    ctor public FillWindow();
+    method public void destroy();
+    method public boolean update(android.service.autofill.augmented.PresentationParams.Area, android.view.View, long);
+    field public static final long FLAG_METADATA_ADDRESS = 1L; // 0x1L
+  }
+
+  public abstract class PresentationParams {
+    method public int getFlags();
+    method public android.service.autofill.augmented.PresentationParams.Area getFullArea();
+    method public android.service.autofill.augmented.PresentationParams.Area getSuggestionArea();
+    field public static final int FLAG_HINT_GRAVITY_BOTTOM = 2; // 0x2
+    field public static final int FLAG_HINT_GRAVITY_LEFT = 4; // 0x4
+    field public static final int FLAG_HINT_GRAVITY_RIGHT = 8; // 0x8
+    field public static final int FLAG_HINT_GRAVITY_TOP = 1; // 0x1
+    field public static final int FLAG_HOST_IME = 16; // 0x10
+    field public static final int FLAG_HOST_SYSTEM = 32; // 0x20
+  }
+
+  public static abstract class PresentationParams.Area {
+    method public android.graphics.Rect getBounds();
+    method public android.service.autofill.augmented.PresentationParams.Area getSubArea(android.graphics.Rect);
+  }
+
+}
+
 package android.service.carrier {
 
   public abstract class ApnService extends android.app.Service {
@@ -4868,6 +4971,58 @@
 
 }
 
+package android.service.contentcapture {
+
+  public final class ContentCaptureEventsRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.util.List<android.view.contentcapture.ContentCaptureEvent> getEvents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.contentcapture.ContentCaptureEventsRequest> CREATOR;
+  }
+
+  public abstract class ContentCaptureService extends android.app.Service {
+    ctor public ContentCaptureService();
+    method public final java.util.Set<android.content.ComponentName> getContentCaptureDisabledActivities();
+    method public final java.util.Set<java.lang.String> getContentCaptureDisabledPackages();
+    method public void onActivitySnapshot(android.service.contentcapture.InteractionSessionId, android.service.contentcapture.SnapshotData);
+    method public abstract void onContentCaptureEventsRequest(android.service.contentcapture.InteractionSessionId, android.service.contentcapture.ContentCaptureEventsRequest);
+    method public void onCreateInteractionSession(android.service.contentcapture.InteractionContext, android.service.contentcapture.InteractionSessionId);
+    method public void onDestroyInteractionSession(android.service.contentcapture.InteractionSessionId);
+    method public final void setActivityContentCaptureEnabled(android.content.ComponentName, boolean);
+    method public final void setContentCaptureWhitelist(java.util.List<java.lang.String>, java.util.List<android.content.ComponentName>);
+    method public final void setPackageContentCaptureEnabled(java.lang.String, boolean);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
+  }
+
+  public final class InteractionContext implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.content.ComponentName getActivityComponent();
+    method public int getDisplayId();
+    method public int getFlags();
+    method public int getTaskId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.contentcapture.InteractionContext> CREATOR;
+    field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1
+    field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2
+  }
+
+  public final class InteractionSessionId implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.contentcapture.InteractionSessionId> CREATOR;
+  }
+
+  public final class SnapshotData implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.app.assist.AssistContent getAssistContent();
+    method public android.os.Bundle getAssistData();
+    method public android.app.assist.AssistStructure getAssistStructure();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.contentcapture.SnapshotData> CREATOR;
+  }
+
+}
+
 package android.service.euicc {
 
   public final class EuiccProfileInfo implements android.os.Parcelable {
@@ -4988,111 +5143,6 @@
 
 }
 
-package android.service.intelligence {
-
-  public final class ContentCaptureEventsRequest implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.util.List<android.view.intelligence.ContentCaptureEvent> getEvents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.service.intelligence.ContentCaptureEventsRequest> CREATOR;
-  }
-
-  public final class FillCallback {
-    method public void onSuccess(android.service.intelligence.FillResponse);
-  }
-
-  public final class FillController {
-    method public void autofill(java.util.List<android.util.Pair<android.view.autofill.AutofillId, android.view.autofill.AutofillValue>>);
-  }
-
-  public final class FillRequest {
-    method public android.view.autofill.AutofillValue getFocusedAutofillValue();
-    method public android.view.autofill.AutofillId getFocusedId();
-    method public android.service.intelligence.PresentationParams getPresentationParams();
-    method public android.service.intelligence.InteractionSessionId getSessionId();
-  }
-
-  public final class FillResponse implements android.os.Parcelable {
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.service.intelligence.FillResponse> CREATOR;
-  }
-
-  public static class FillResponse.Builder {
-    ctor public FillResponse.Builder();
-    method public android.service.intelligence.FillResponse build();
-    method public android.service.intelligence.FillResponse.Builder setFillWindow(android.service.intelligence.FillWindow);
-    method public android.service.intelligence.FillResponse.Builder setIgnoredIds(java.util.List<android.view.autofill.AutofillId>);
-  }
-
-  public final class FillWindow {
-    ctor public FillWindow();
-    method public void destroy();
-    method public boolean update(android.service.intelligence.PresentationParams.Area, android.view.View, long);
-    field public static final long FLAG_METADATA_ADDRESS = 1L; // 0x1L
-  }
-
-  public final class InteractionContext implements android.os.Parcelable {
-    method public int describeContents();
-    method public android.content.ComponentName getActivityComponent();
-    method public int getDisplayId();
-    method public int getFlags();
-    method public int getTaskId();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.service.intelligence.InteractionContext> CREATOR;
-    field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1
-    field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2
-  }
-
-  public final class InteractionSessionId implements android.os.Parcelable {
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.service.intelligence.InteractionSessionId> CREATOR;
-  }
-
-  public abstract class PresentationParams {
-    method public int getFlags();
-    method public android.service.intelligence.PresentationParams.Area getFullArea();
-    method public android.service.intelligence.PresentationParams.Area getSuggestionArea();
-    field public static final int FLAG_HINT_GRAVITY_BOTTOM = 2; // 0x2
-    field public static final int FLAG_HINT_GRAVITY_LEFT = 4; // 0x4
-    field public static final int FLAG_HINT_GRAVITY_RIGHT = 8; // 0x8
-    field public static final int FLAG_HINT_GRAVITY_TOP = 1; // 0x1
-    field public static final int FLAG_HOST_IME = 16; // 0x10
-    field public static final int FLAG_HOST_SYSTEM = 32; // 0x20
-  }
-
-  public static abstract class PresentationParams.Area {
-    method public android.graphics.Rect getBounds();
-    method public android.service.intelligence.PresentationParams.Area getSubArea(android.graphics.Rect);
-  }
-
-  public abstract class SmartSuggestionsService extends android.app.Service {
-    ctor public SmartSuggestionsService();
-    method public final java.util.Set<android.content.ComponentName> getContentCaptureDisabledActivities();
-    method public final java.util.Set<java.lang.String> getContentCaptureDisabledPackages();
-    method public void onActivitySnapshot(android.service.intelligence.InteractionSessionId, android.service.intelligence.SnapshotData);
-    method public abstract void onContentCaptureEventsRequest(android.service.intelligence.InteractionSessionId, android.service.intelligence.ContentCaptureEventsRequest);
-    method public void onCreateInteractionSession(android.service.intelligence.InteractionContext, android.service.intelligence.InteractionSessionId);
-    method public void onDestroyInteractionSession(android.service.intelligence.InteractionSessionId);
-    method public void onFillRequest(android.service.intelligence.InteractionSessionId, android.service.intelligence.FillRequest, android.os.CancellationSignal, android.service.intelligence.FillController, android.service.intelligence.FillCallback);
-    method public final void setActivityContentCaptureEnabled(android.content.ComponentName, boolean);
-    method public final void setContentCaptureWhitelist(java.util.List<java.lang.String>, java.util.List<android.content.ComponentName>);
-    method public final void setPackageContentCaptureEnabled(java.lang.String, boolean);
-    field public static final java.lang.String SERVICE_INTERFACE = "android.service.intelligence.SmartSuggestionsService";
-  }
-
-  public final class SnapshotData implements android.os.Parcelable {
-    method public int describeContents();
-    method public android.app.assist.AssistContent getAssistContent();
-    method public android.os.Bundle getAssistData();
-    method public android.app.assist.AssistStructure getAssistStructure();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.service.intelligence.SnapshotData> CREATOR;
-  }
-
-}
-
 package android.service.notification {
 
   public final class Adjustment implements android.os.Parcelable {
@@ -7269,7 +7319,7 @@
 
 }
 
-package android.view.intelligence {
+package android.view.contentcapture {
 
   public final class ContentCaptureEvent implements android.os.Parcelable {
     method public int describeContents();
@@ -7278,13 +7328,13 @@
     method public android.view.autofill.AutofillId getId();
     method public java.lang.CharSequence getText();
     method public int getType();
-    method public android.view.intelligence.ViewNode getViewNode();
+    method public android.view.contentcapture.ViewNode getViewNode();
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.view.intelligence.ContentCaptureEvent> CREATOR;
-    field public static final int TYPE_ACTIVITY_PAUSED = 3; // 0x3
-    field public static final int TYPE_ACTIVITY_RESUMED = 2; // 0x2
-    field public static final int TYPE_ACTIVITY_STARTED = 1; // 0x1
-    field public static final int TYPE_ACTIVITY_STOPPED = 4; // 0x4
+    field public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureEvent> CREATOR;
+    field public static final deprecated int TYPE_ACTIVITY_PAUSED = 3; // 0x3
+    field public static final deprecated int TYPE_ACTIVITY_RESUMED = 2; // 0x2
+    field public static final deprecated int TYPE_ACTIVITY_STARTED = 1; // 0x1
+    field public static final deprecated int TYPE_ACTIVITY_STOPPED = 4; // 0x4
     field public static final int TYPE_VIEW_APPEARED = 5; // 0x5
     field public static final int TYPE_VIEW_DISAPPEARED = 6; // 0x6
     field public static final int TYPE_VIEW_TEXT_CHANGED = 7; // 0x7
diff --git a/api/test-current.txt b/api/test-current.txt
index 46cbb52..91e8ec6 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -299,7 +299,11 @@
 
 package android.content {
 
-  public abstract class ContentResolver {
+  public class ContentProviderClient implements java.lang.AutoCloseable android.content.ContentInterface {
+    method public void setDetectNotResponding(long);
+  }
+
+  public abstract class ContentResolver implements android.content.ContentInterface {
     method public static java.lang.String[] getSyncAdapterPackagesForAuthorityAsUser(java.lang.String, int);
   }
 
@@ -983,6 +987,11 @@
     field public static final android.net.Uri CORP_CONTENT_URI;
   }
 
+  public final class MediaStore {
+    method public static void deleteContributedMedia(android.content.Context, java.lang.String);
+    method public static long getContributedMediaSize(android.content.Context, java.lang.String);
+  }
+
   public final class Settings {
     field public static final java.lang.String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
   }
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 52a2ab4..55dbc17 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -557,7 +557,7 @@
 
         @Override
         public void onExecute(IContentProvider provider) throws Exception {
-            Bundle result = provider.call(null, mMethod, mArg, mExtras);
+            Bundle result = provider.call(null, mUri.getAuthority(), mMethod, mArg, mExtras);
             if (result != null) {
                 result.size(); // unpack
             }
diff --git a/cmds/device_config/Android.mk b/cmds/device_config/Android.mk
new file mode 100644
index 0000000..4041e01
--- /dev/null
+++ b/cmds/device_config/Android.mk
@@ -0,0 +1,10 @@
+# Copyright 2018 The Android Open Source Project
+#
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := device_config
+LOCAL_SRC_FILES := device_config
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_PREBUILT)
diff --git a/cmds/device_config/device_config b/cmds/device_config/device_config
new file mode 100755
index 0000000..a949bd5
--- /dev/null
+++ b/cmds/device_config/device_config
@@ -0,0 +1,2 @@
+#!/system/bin/sh
+cmd device_config "$@"
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.cpp b/cmds/hid/jni/com_android_commands_hid_Device.cpp
index b3e287b..d4fdf85 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.cpp
+++ b/cmds/hid/jni/com_android_commands_hid_Device.cpp
@@ -45,6 +45,7 @@
 
 static struct {
     jmethodID onDeviceOpen;
+    jmethodID onDeviceGetReport;
     jmethodID onDeviceError;
 } gDeviceCallbackClassInfo;
 
@@ -82,6 +83,13 @@
     checkAndClearException(env, "onDeviceOpen");
 }
 
+void DeviceCallback::onDeviceGetReport(uint32_t requestId, uint8_t reportId) {
+    JNIEnv* env = getJNIEnv();
+    env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceGetReport,
+            requestId, reportId);
+    checkAndClearException(env, "onDeviceGetReport");
+}
+
 JNIEnv* DeviceCallback::getJNIEnv() {
     JNIEnv* env;
     mJavaVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
@@ -103,8 +111,7 @@
         return nullptr;
     }
 
-    struct uhid_event ev;
-    memset(&ev, 0, sizeof(ev));
+    struct uhid_event ev = {};
     ev.type = UHID_CREATE2;
     strlcpy(reinterpret_cast<char*>(ev.u.create2.name), name, sizeof(ev.u.create2.name));
     memcpy(&ev.u.create2.rd_data, descriptor.data(),
@@ -152,8 +159,7 @@
     } else {
         LOGE("Could not remove fd, ALooper_forThread() returned NULL!");
     }
-    struct uhid_event ev;
-    memset(&ev, 0, sizeof(ev));
+    struct uhid_event ev = {};
     ev.type = UHID_DESTROY;
     TEMP_FAILURE_RETRY(::write(mFd, &ev, sizeof(ev)));
     ::close(mFd);
@@ -166,8 +172,7 @@
         return;
     }
 
-    struct uhid_event ev;
-    memset(&ev, 0, sizeof(ev));
+    struct uhid_event ev = {};
     ev.type = UHID_INPUT2;
     ev.u.input2.size = report.size();
     memcpy(&ev.u.input2.data, report.data(), report.size() * sizeof(ev.u.input2.data[0]));
@@ -177,6 +182,20 @@
     }
 }
 
+void Device::sendGetFeatureReportReply(uint32_t id, const std::vector<uint8_t>& report) const {
+    struct uhid_event ev = {};
+    ev.type = UHID_GET_REPORT_REPLY;
+    ev.u.get_report_reply.id = id;
+    ev.u.get_report_reply.err = report.size() == 0 ? EIO : 0;
+    ev.u.get_report_reply.size = report.size();
+    memcpy(&ev.u.get_report_reply.data, report.data(),
+            report.size() * sizeof(ev.u.get_report_reply.data[0]));
+    ssize_t ret = TEMP_FAILURE_RETRY(::write(mFd, &ev, sizeof(ev)));
+    if (ret < 0 || ret != sizeof(ev)) {
+        LOGE("Failed to send hid event (UHID_GET_REPORT_REPLY): %s", strerror(errno));
+    }
+}
+
 int Device::handleEvents(int events) {
     if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
         LOGE("uhid node was closed or an error occurred. events=0x%x", events);
@@ -193,6 +212,11 @@
 
     if (ev.type == UHID_OPEN) {
         mDeviceCallback->onDeviceOpen();
+    } else if (ev.type == UHID_GET_REPORT) {
+        mDeviceCallback->onDeviceGetReport(ev.u.get_report.id, ev.u.get_report.rnum);
+    } else if (ev.type == UHID_SET_REPORT) {
+        LOGE("UHID_SET_REPORT is currently not supported");
+        return 0;
     }
 
     return 1;
@@ -201,9 +225,13 @@
 } // namespace uhid
 
 std::vector<uint8_t> getData(JNIEnv* env, jbyteArray javaArray) {
+    std::vector<uint8_t> data;
+    if (javaArray == nullptr) {
+        return data;
+    }
+
     ScopedByteArrayRO scopedArray(env, javaArray);
     size_t size = scopedArray.size();
-    std::vector<uint8_t> data;
     data.reserve(size);
     for (size_t i = 0; i < size; i++) {
         data.push_back(static_cast<uint8_t>(scopedArray[i]));
@@ -237,6 +265,17 @@
     }
 }
 
+static void sendGetFeatureReportReply(JNIEnv* env, jclass /* clazz */, jlong ptr, jint id,
+        jbyteArray rawReport) {
+    uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr);
+    if (d) {
+        std::vector<uint8_t> report = getData(env, rawReport);
+        d->sendGetFeatureReportReply(id, report);
+    } else {
+        LOGE("Could not send get feature report reply, Device* is null!");
+    }
+}
+
 static void closeDevice(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) {
     uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr);
     if (d) {
@@ -250,6 +289,8 @@
             "Lcom/android/commands/hid/Device$DeviceCallback;)J",
             reinterpret_cast<void*>(openDevice) },
     { "nativeSendReport", "(J[B)V", reinterpret_cast<void*>(sendReport) },
+    { "nativeSendGetFeatureReportReply", "(JI[B)V",
+            reinterpret_cast<void*>(sendGetFeatureReportReply) },
     { "nativeCloseDevice", "(J)V", reinterpret_cast<void*>(closeDevice) },
 };
 
@@ -261,6 +302,8 @@
     }
     uhid::gDeviceCallbackClassInfo.onDeviceOpen =
             env->GetMethodID(clazz, "onDeviceOpen", "()V");
+    uhid::gDeviceCallbackClassInfo.onDeviceGetReport =
+            env->GetMethodID(clazz, "onDeviceGetReport", "(II)V");
     uhid::gDeviceCallbackClassInfo.onDeviceError =
             env->GetMethodID(clazz, "onDeviceError", "()V");
     if (uhid::gDeviceCallbackClassInfo.onDeviceOpen == NULL ||
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.h b/cmds/hid/jni/com_android_commands_hid_Device.h
index 61a1f76..892c7cd 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.h
+++ b/cmds/hid/jni/com_android_commands_hid_Device.h
@@ -28,6 +28,7 @@
     ~DeviceCallback();
 
     void onDeviceOpen();
+    void onDeviceGetReport(uint32_t requestId, uint8_t reportId);
     void onDeviceError();
 
 private:
@@ -45,6 +46,7 @@
     ~Device();
 
     void sendReport(const std::vector<uint8_t>& report) const;
+    void sendGetFeatureReportReply(uint32_t id, const std::vector<uint8_t>& report) const;
     void close();
 
     int handleEvents(int events);
diff --git a/cmds/hid/src/com/android/commands/hid/Device.java b/cmds/hid/src/com/android/commands/hid/Device.java
index 8c52a8e..616d411 100644
--- a/cmds/hid/src/com/android/commands/hid/Device.java
+++ b/cmds/hid/src/com/android/commands/hid/Device.java
@@ -23,6 +23,7 @@
 import android.os.MessageQueue;
 import android.os.SystemClock;
 import android.util.Log;
+import android.util.SparseArray;
 
 import com.android.internal.os.SomeArgs;
 
@@ -31,11 +32,14 @@
 
     private static final int MSG_OPEN_DEVICE = 1;
     private static final int MSG_SEND_REPORT = 2;
-    private static final int MSG_CLOSE_DEVICE = 3;
+    private static final int MSG_SEND_GET_FEATURE_REPORT_REPLY = 3;
+    private static final int MSG_CLOSE_DEVICE = 4;
 
     private final int mId;
     private final HandlerThread mThread;
     private final DeviceHandler mHandler;
+    // mFeatureReports is limited to 256 entries, because the report number is 8-bit
+    private final SparseArray<byte[]> mFeatureReports;
     private long mTimeToSend;
 
     private final Object mCond = new Object();
@@ -47,13 +51,16 @@
     private static native long nativeOpenDevice(String name, int id, int vid, int pid,
             byte[] descriptor, DeviceCallback callback);
     private static native void nativeSendReport(long ptr, byte[] data);
+    private static native void nativeSendGetFeatureReportReply(long ptr, int id, byte[] data);
     private static native void nativeCloseDevice(long ptr);
 
-    public Device(int id, String name, int vid, int pid, byte[] descriptor, byte[] report) {
+    public Device(int id, String name, int vid, int pid, byte[] descriptor,
+            byte[] report, SparseArray<byte[]> featureReports) {
         mId = id;
         mThread = new HandlerThread("HidDeviceHandler");
         mThread.start();
         mHandler = new DeviceHandler(mThread.getLooper());
+        mFeatureReports = featureReports;
         SomeArgs args = SomeArgs.obtain();
         args.argi1 = id;
         args.argi2 = vid;
@@ -113,6 +120,13 @@
                         Log.e(TAG, "Tried to send report to closed device.");
                     }
                     break;
+                case MSG_SEND_GET_FEATURE_REPORT_REPLY:
+                    if (mPtr != 0) {
+                        nativeSendGetFeatureReportReply(mPtr, msg.arg1, (byte[]) msg.obj);
+                    } else {
+                        Log.e(TAG, "Tried to send feature report reply to closed device.");
+                    }
+                    break;
                 case MSG_CLOSE_DEVICE:
                     if (mPtr != 0) {
                         nativeCloseDevice(mPtr);
@@ -145,6 +159,23 @@
             mHandler.resumeEvents();
         }
 
+        public void onDeviceGetReport(int requestId, int reportId) {
+            byte[] report = mFeatureReports.get(reportId);
+
+            if (report == null) {
+                Log.e(TAG, "Requested feature report " + reportId + " is not specified");
+            }
+
+            Message msg;
+            msg = mHandler.obtainMessage(MSG_SEND_GET_FEATURE_REPORT_REPLY, requestId, 0, report);
+
+            // Message is set to asynchronous so it won't be blocked by synchronization
+            // barrier during UHID_OPEN. This is necessary for drivers that do
+            // UHID_GET_REPORT requests during probe.
+            msg.setAsynchronous(true);
+            mHandler.sendMessageAtTime(msg, mTimeToSend);
+        }
+
         public void onDeviceError() {
             Log.e(TAG, "Device error occurred, closing /dev/uhid");
             Message msg = mHandler.obtainMessage(MSG_CLOSE_DEVICE);
diff --git a/cmds/hid/src/com/android/commands/hid/Event.java b/cmds/hid/src/com/android/commands/hid/Event.java
index c6a37bd..746e372 100644
--- a/cmds/hid/src/com/android/commands/hid/Event.java
+++ b/cmds/hid/src/com/android/commands/hid/Event.java
@@ -19,6 +19,7 @@
 import android.util.JsonReader;
 import android.util.JsonToken;
 import android.util.Log;
+import android.util.SparseArray;
 
 import java.io.InputStreamReader;
 import java.io.IOException;
@@ -39,6 +40,7 @@
     private int mVid;
     private int mPid;
     private byte[] mReport;
+    private SparseArray<byte[]> mFeatureReports;
     private int mDuration;
 
     public int getId() {
@@ -69,6 +71,10 @@
         return mReport;
     }
 
+    public SparseArray<byte[]> getFeatureReports() {
+        return mFeatureReports;
+    }
+
     public int getDuration() {
         return mDuration;
     }
@@ -81,6 +87,7 @@
             + ", vid=" + mVid
             + ", pid=" + mPid
             + ", report=" + Arrays.toString(mReport)
+            + ", feature_reports=" + mFeatureReports.toString()
             + ", duration=" + mDuration
             + "}";
     }
@@ -112,6 +119,10 @@
             mEvent.mReport = report;
         }
 
+        public void setFeatureReports(SparseArray<byte[]> reports) {
+            mEvent.mFeatureReports = reports;
+        }
+
         public void setVid(int vid) {
             mEvent.mVid = vid;
         }
@@ -185,6 +196,9 @@
                             case "report":
                                 eb.setReport(readData());
                                 break;
+                            case "feature_reports":
+                                eb.setFeatureReports(readFeatureReports());
+                                break;
                             case "duration":
                                 eb.setDuration(readInt());
                                 break;
@@ -234,6 +248,47 @@
             return Integer.decode(val);
         }
 
+        private SparseArray<byte[]> readFeatureReports()
+                throws IllegalStateException, IOException {
+            SparseArray<byte[]> featureReports = new SparseArray();
+            try {
+                mReader.beginArray();
+                while (mReader.hasNext()) {
+                    // If "id" is not specified, it defaults to 0, which means
+                    // report does not contain report ID (based on HID specs).
+                    int id = 0;
+                    byte[] data = null;
+                    mReader.beginObject();
+                    while (mReader.hasNext()) {
+                        String name = mReader.nextName();
+                        switch (name) {
+                            case "id":
+                                id = readInt();
+                                break;
+                            case "data":
+                                data = readData();
+                                break;
+                            default:
+                                consumeRemainingElements();
+                                mReader.endObject();
+                                throw new IllegalStateException("Invalid key in feature report: "
+                                        + name);
+                        }
+                    }
+                    mReader.endObject();
+                    if (data != null)
+                        featureReports.put(id, data);
+                }
+                mReader.endArray();
+            } catch (IllegalStateException|NumberFormatException e) {
+                consumeRemainingElements();
+                mReader.endArray();
+                throw new IllegalStateException("Encountered malformed data.", e);
+            } finally {
+                return featureReports;
+            }
+        }
+
         private void consumeRemainingElements() throws IOException {
             while (mReader.hasNext()) {
                 mReader.skipValue();
diff --git a/cmds/hid/src/com/android/commands/hid/Hid.java b/cmds/hid/src/com/android/commands/hid/Hid.java
index 234e47f..54ac1b0 100644
--- a/cmds/hid/src/com/android/commands/hid/Hid.java
+++ b/cmds/hid/src/com/android/commands/hid/Hid.java
@@ -119,7 +119,7 @@
         }
         int id = e.getId();
         Device d = new Device(id, e.getName(), e.getVendorId(), e.getProductId(),
-                e.getDescriptor(), e.getReport());
+                e.getDescriptor(), e.getReport(), e.getFeatureReports());
         mDevices.append(id, d);
     }
 
diff --git a/cmds/incident_helper/OWNERS b/cmds/incident_helper/OWNERS
index 1a68a32..cede4ea 100644
--- a/cmds/incident_helper/OWNERS
+++ b/cmds/incident_helper/OWNERS
@@ -1,2 +1,3 @@
-jinyithu@google.com
+joeo@google.com
 kwekua@google.com
+yanmin@google.com
diff --git a/cmds/incidentd/OWNERS b/cmds/incidentd/OWNERS
index 1a68a32..cede4ea 100644
--- a/cmds/incidentd/OWNERS
+++ b/cmds/incidentd/OWNERS
@@ -1,2 +1,3 @@
-jinyithu@google.com
+joeo@google.com
 kwekua@google.com
+yanmin@google.com
diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp
index 74cda1d..04819ec 100644
--- a/cmds/incidentd/src/FdBuffer.cpp
+++ b/cmds/incidentd/src/FdBuffer.cpp
@@ -18,7 +18,7 @@
 
 #include "FdBuffer.h"
 
-#include <cutils/log.h>
+#include <log/log.h>
 #include <utils/SystemClock.h>
 
 #include <fcntl.h>
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index 3d892ad..f8fb4a6 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -29,7 +29,7 @@
 #include <binder/IResultReceiver.h>
 #include <binder/IServiceManager.h>
 #include <binder/IShellCallback.h>
-#include <cutils/log.h>
+#include <log/log.h>
 #include <private/android_filesystem_config.h>
 #include <utils/Looper.h>
 
diff --git a/cmds/incidentd/src/PrivacyBuffer.cpp b/cmds/incidentd/src/PrivacyBuffer.cpp
index 6967e33..08f535d 100644
--- a/cmds/incidentd/src/PrivacyBuffer.cpp
+++ b/cmds/incidentd/src/PrivacyBuffer.cpp
@@ -21,7 +21,7 @@
 
 #include <android-base/file.h>
 #include <android/util/protobuf.h>
-#include <cutils/log.h>
+#include <log/log.h>
 
 namespace android {
 namespace os {
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 41a2021..78d8e29 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -30,6 +30,7 @@
 import "frameworks/base/core/proto/android/server/location/enums.proto";
 import "frameworks/base/core/proto/android/service/procstats_enum.proto";
 import "frameworks/base/core/proto/android/stats/enums.proto";
+import "frameworks/base/core/proto/android/stats/docsui/docsui_enums.proto";
 import "frameworks/base/core/proto/android/stats/launcher/launcher.proto";
 import "frameworks/base/core/proto/android/telecomm/enums.proto";
 import "frameworks/base/core/proto/android/telephony/enums.proto";
@@ -159,6 +160,15 @@
         PhenotypeFlagStateChanged phenotype_flag_state_changed = 101;
         BinaryPushStateChanged binary_push_state_changed = 102;
         DevicePolicyEvent device_policy_event = 103;
+        DocsUIFileOperationCanceledReported docs_ui_file_op_canceled = 104;
+        DocsUIFileOperationCopyMoveModeReported docs_ui_file_op_copy_move_mode_reported = 105;
+        DocsUIFileOperationFailureReported docs_ui_file_op_failure = 106;
+        DocsUIFileOperationReported docs_ui_provider_file_op = 107;
+        DocsUIInvalidScopedAccessRequestReported docs_ui_invalid_scoped_access_request = 108;
+        DocsUILaunchReported docs_ui_launch_reported = 109;
+        DocsUIRootVisitedReported docs_ui_root_visited = 110;
+        DocsUIStartupMsReported docs_ui_startup_ms = 111;
+        DocsUIUserActionReported docs_ui_user_action_reported = 112;
     }
 
     // Pulled events will start at field 10000.
@@ -1501,17 +1511,17 @@
     /**
      * Where the action is happening
      */
-    optional android.app.settings.PageId pageId = 3;
+    optional android.app.settings.PageId page_id = 3;
 
     /**
      * What preference changed in this event.
      */
-    optional string changedPreferenceKey = 4;
+    optional string changed_preference_key = 4;
 
     /**
      * The new value of the changed preference.
      */
-    optional int64 changedPreferenceIntValue = 5;
+    optional int64 changed_preference_int_value = 5;
 }
 
 /**
@@ -3467,3 +3477,103 @@
     // A parameter specifying a list of package names, bundle extras or string parameters.
     optional android.stats.devicepolicy.StringList string_list_value = 6 [(log_mode) = MODE_BYTES];
 }
+
+/**
+ * Logs when DocumentsUI is started, and how. Call this when DocumentsUI first starts up.
+ *
+ * Logged from:
+ *     package/app/DocumentsUI/src/com/android/documentsui/Metrics.java
+ */
+message DocsUILaunchReported {
+    optional android.stats.docsui.LaunchAction launch_action = 1;
+    optional bool has_initial_uri = 2;
+    optional android.stats.docsui.MimeType mime_type = 3;
+    optional android.stats.docsui.Root initial_root = 4;
+}
+
+/**
+ * Logs root/app visited event in file managers/picker. Call this when the user
+ * taps on root/app in hamburger menu.
+ *
+ * Logged from:
+ *     package/app/DocumentsUI/src/com/android/documentsui/Metrics.java
+ */
+message DocsUIRootVisitedReported {
+    optional android.stats.docsui.ContextScope scope = 1;
+    optional android.stats.docsui.Root root = 2;
+}
+
+/**
+ * Logs file operation stats. Call this when a file operation has completed.
+ *
+ * Logged from:
+ *     package/app/DocumentsUI/src/com/android/documentsui/Metrics.java
+ */
+message DocsUIFileOperationReported {
+    optional android.stats.docsui.Provider provider = 1;
+    optional android.stats.docsui.FileOperation file_op = 2;
+}
+
+/**
+ * Logs file operation stats. Call this when a copy/move operation has completed with a specific
+ * mode.
+ *
+ * Logged from:
+ *     package/app/DocumentsUI/src/com/android/documentsui/Metrics.java
+ */
+message DocsUIFileOperationCopyMoveModeReported {
+    optional android.stats.docsui.FileOperation file_op = 1;
+    optional android.stats.docsui.CopyMoveOpMode mode = 2;
+}
+
+
+/**
+ * Logs file sub operation stats. Call this when a file operation has failed.
+ *
+ * Logged from:
+ *     package/app/DocumentsUI/src/com/android/documentsui/Metrics.java
+ */
+message DocsUIFileOperationFailureReported {
+    optional android.stats.docsui.Authority authority = 1;
+    optional android.stats.docsui.SubFileOperation sub_op = 2;
+}
+
+/**
+* Logs the cancellation of a file operation. Call this when a job is canceled
+*
+* Logged from:
+*     package/app/DocumentsUI/src/com/android/documentsui/Metrics.java
+*/
+message DocsUIFileOperationCanceledReported {
+    optional android.stats.docsui.FileOperation file_op = 1;
+}
+
+/**
+ * Logs startup time in milliseconds.
+ *
+ * Logged from:
+ *     package/app/DocumentsUI/src/com/android/documentsui/Metrics.java
+ */
+message DocsUIStartupMsReported {
+    optional int32 startup_millis = 1;
+}
+
+/**
+ * Logs the action that was started by user.
+ *
+ * Logged from:
+ *     package/app/DocumentsUI/src/com/android/documentsui/Metrics.java
+ */
+message DocsUIUserActionReported {
+    optional android.stats.docsui.UserAction action = 1;
+}
+
+/**
+ * Logs the invalid type when invalid scoped access is requested.
+ *
+ * Logged from:
+ *     package/app/DocumentsUI/src/com/android/documentsui/ScopedAccessMetrics.java
+ */
+message DocsUIInvalidScopedAccessRequestReported {
+    optional android.stats.docsui.InvalidScopedAccess type = 1;
+}
\ No newline at end of file
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 579ef93..01c7028 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -2904,8 +2904,6 @@
 Lcom/android/internal/telephony/dataconnection/DcTracker$RecoveryAction;->isAggressiveRecovery(I)Z
 Lcom/android/internal/telephony/dataconnection/DcTracker;->cancelReconnectAlarm(Lcom/android/internal/telephony/dataconnection/ApnContext;)V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->cleanUpAllConnections(Ljava/lang/String;)V
-Lcom/android/internal/telephony/dataconnection/DcTracker;->cleanUpAllConnections(ZLjava/lang/String;)Z
-Lcom/android/internal/telephony/dataconnection/DcTracker;->cleanUpConnection(ZLcom/android/internal/telephony/dataconnection/ApnContext;)V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->createAllApnList()V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->getActiveApnTypes()[Ljava/lang/String;
 Lcom/android/internal/telephony/dataconnection/DcTracker;->getOverallState()Lcom/android/internal/telephony/DctConstants$State;
@@ -2936,7 +2934,6 @@
 Lcom/android/internal/telephony/dataconnection/DcTracker;->notifyOffApnsOfAvailability(Ljava/lang/String;)V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->onActionIntentDataStallAlarm(Landroid/content/Intent;)V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->onActionIntentProvisioningApnAlarm(Landroid/content/Intent;)V
-Lcom/android/internal/telephony/dataconnection/DcTracker;->onCleanUpAllConnections(Ljava/lang/String;)V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->onRecordsLoadedOrSubIdChanged()V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->onSetUserDataEnabled(Z)V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->onTrySetupData(Lcom/android/internal/telephony/dataconnection/ApnContext;)Z
@@ -2945,7 +2942,6 @@
 Lcom/android/internal/telephony/dataconnection/DcTracker;->resetPollStats()V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->restartDataStallAlarm()V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->setInitialAttachApn()V
-Lcom/android/internal/telephony/dataconnection/DcTracker;->setInternalDataEnabled(ZLandroid/os/Message;)Z
 Lcom/android/internal/telephony/dataconnection/DcTracker;->setPreferredApn(I)V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->setRadio(Z)V
 Lcom/android/internal/telephony/dataconnection/DcTracker;->setupDataOnConnectableApns(Ljava/lang/String;)V
diff --git a/core/java/android/annotation/UnsupportedAppUsage.java b/core/java/android/annotation/UnsupportedAppUsage.java
index 28145a0..65e3f25 100644
--- a/core/java/android/annotation/UnsupportedAppUsage.java
+++ b/core/java/android/annotation/UnsupportedAppUsage.java
@@ -18,8 +18,10 @@
 import static java.lang.annotation.ElementType.CONSTRUCTOR;
 import static java.lang.annotation.ElementType.FIELD;
 import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
 import static java.lang.annotation.RetentionPolicy.CLASS;
 
+import java.lang.annotation.Repeatable;
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
@@ -40,7 +42,8 @@
  * {@hide}
  */
 @Retention(CLASS)
-@Target({CONSTRUCTOR, METHOD, FIELD})
+@Target({CONSTRUCTOR, METHOD, FIELD, TYPE})
+@Repeatable(UnsupportedAppUsage.Container.class)
 public @interface UnsupportedAppUsage {
 
     /**
@@ -90,4 +93,27 @@
      * @return A dex API signature.
      */
     String expectedSignature() default "";
+
+    /**
+     * The signature of an implicit (not present in the source) member that forms part of the
+     * hiddenapi.
+     *
+     * <p>Allows access to non-SDK API elements that are not represented in the input source to be
+     * managed.
+     *
+     * <p>This must only be used when applying the annotation to a type, using it in any other
+     * situation is an error.
+     *
+     * @return A dex API signature.
+     */
+    String implicitMember() default "";
+
+    /**
+     * Container for {@link UnsupportedAppUsage} that allows it to be applied repeatedly to types.
+     */
+    @Retention(CLASS)
+    @Target(TYPE)
+    @interface Container {
+        UnsupportedAppUsage[] value();
+    }
 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f3f065a..61b9d55 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -121,8 +121,8 @@
 import android.view.autofill.AutofillManager.AutofillClient;
 import android.view.autofill.AutofillPopupWindow;
 import android.view.autofill.IAutofillWindowPresenter;
-import android.view.intelligence.ContentCaptureEvent;
-import android.view.intelligence.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureManager;
 import android.widget.AdapterView;
 import android.widget.Toast;
 import android.widget.Toolbar;
@@ -1723,15 +1723,7 @@
         if (mAutoFillResetNeeded) {
             if (!mAutoFillIgnoreFirstResumePause) {
                 View focus = getCurrentFocus();
-                // On Activity rotation situation (mRestoredFromBundle is true),
-                // we should not call on AutofillManager in onResume()
-                // since the next Layout pass will do that.
-                // However, there are both cases where Activity#getCurrentFocus()
-                // will return null (window not preserved) and not null (window IS
-                // preserved), so we need to explicitly check for mRestoredFromBundle
-                // here.
-                if (!mRestoredFromBundle && focus != null
-                        && focus.canNotifyAutofillEnterExitEvent()) {
+                if (focus != null && focus.canNotifyAutofillEnterExitEvent()) {
                     // TODO: in Activity killed/recreated case, i.e. SessionLifecycleTest#
                     // testDatasetVisibleWhileAutofilledAppIsLifecycled: the View's initial
                     // window visibility after recreation is INVISIBLE in onResume() and next frame
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 41166dd..492aad9 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -162,7 +162,6 @@
 import com.android.org.conscrypt.TrustedCertificateStore;
 import com.android.server.am.MemInfoDumpProto;
 
-import dalvik.system.BaseDexClassLoader;
 import dalvik.system.CloseGuard;
 import dalvik.system.VMDebug;
 import dalvik.system.VMRuntime;
@@ -5948,16 +5947,6 @@
             HardwareRenderer.setIsolatedProcess(true);
         }
 
-        // If we use profiles, setup the dex reporter to notify package manager
-        // of any relevant dex loads. The idle maintenance job will use the information
-        // reported to optimize the loaded dex files.
-        // Note that we only need one global reporter per app.
-        // Make sure we do this before calling onCreate so that we can capture the
-        // complete application startup.
-        if (SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
-            BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
-        }
-
         // Install the Network Security Config Provider. This must happen before the application
         // code is loaded to prevent issues with instances of TLS objects being created before
         // the provider is installed.
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 3069be6..f2fb33f 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -476,9 +476,11 @@
     public static final int OP_READ_MEDIA_IMAGES = 85;
     /** @hide Write media of image type. */
     public static final int OP_WRITE_MEDIA_IMAGES = 86;
+    /** @hide Has a legacy (non-isolated) view of storage. */
+    public static final int OP_LEGACY_STORAGE = 87;
     /** @hide */
     @UnsupportedAppUsage
-    public static final int _NUM_OP = 87;
+    public static final int _NUM_OP = 88;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -745,6 +747,8 @@
     public static final String OPSTR_READ_MEDIA_IMAGES = "android:read_media_images";
     /** @hide Write media of image type. */
     public static final String OPSTR_WRITE_MEDIA_IMAGES = "android:write_media_images";
+    /** @hide Has a legacy (non-isolated) view of storage. */
+    public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage";
 
     // Warning: If an permission is added here it also has to be added to
     // com.android.packageinstaller.permission.utils.EventLogger
@@ -903,6 +907,7 @@
             OP_WRITE_MEDIA_VIDEO,               // WRITE_MEDIA_VIDEO
             OP_READ_MEDIA_IMAGES,               // READ_MEDIA_IMAGES
             OP_WRITE_MEDIA_IMAGES,              // WRITE_MEDIA_IMAGES
+            OP_LEGACY_STORAGE,                  // LEGACY_STORAGE
     };
 
     /**
@@ -996,6 +1001,7 @@
             OPSTR_WRITE_MEDIA_VIDEO,
             OPSTR_READ_MEDIA_IMAGES,
             OPSTR_WRITE_MEDIA_IMAGES,
+            OPSTR_LEGACY_STORAGE,
     };
 
     /**
@@ -1090,6 +1096,7 @@
             "WRITE_MEDIA_VIDEO",
             "READ_MEDIA_IMAGES",
             "WRITE_MEDIA_IMAGES",
+            "LEGACY_STORAGE",
     };
 
     /**
@@ -1185,6 +1192,7 @@
             null, // no permission for OP_WRITE_MEDIA_VIDEO
             Manifest.permission.READ_MEDIA_IMAGES,
             null, // no permission for OP_WRITE_MEDIA_IMAGES
+            null, // no permission for OP_LEGACY_STORAGE
     };
 
     /**
@@ -1280,6 +1288,7 @@
             null, // WRITE_MEDIA_VIDEO
             null, // READ_MEDIA_IMAGES
             null, // WRITE_MEDIA_IMAGES
+            null, // LEGACY_STORAGE
     };
 
     /**
@@ -1374,6 +1383,7 @@
             false, // WRITE_MEDIA_VIDEO
             false, // READ_MEDIA_IMAGES
             false, // WRITE_MEDIA_IMAGES
+            false, // LEGACY_STORAGE
     };
 
     /**
@@ -1467,6 +1477,7 @@
             AppOpsManager.MODE_ERRORED, // WRITE_MEDIA_VIDEO
             AppOpsManager.MODE_ALLOWED, // READ_MEDIA_IMAGES
             AppOpsManager.MODE_ERRORED, // WRITE_MEDIA_IMAGES
+            AppOpsManager.MODE_DEFAULT, // LEGACY_STORAGE
     };
 
     /**
@@ -1564,6 +1575,7 @@
             false, // WRITE_MEDIA_VIDEO
             false, // READ_MEDIA_IMAGES
             false, // WRITE_MEDIA_IMAGES
+            false, // LEGACY_STORAGE
     };
 
     /**
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 759763b..d46dbed 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -57,6 +57,7 @@
 
 import com.android.internal.util.ArrayUtils;
 
+import dalvik.system.BaseDexClassLoader;
 import dalvik.system.VMRuntime;
 
 import java.io.File;
@@ -949,6 +950,15 @@
         if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
             return;
         }
+
+        // If we use profiles, setup the dex reporter to notify package manager
+        // of any relevant dex loads. The idle maintenance job will use the information
+        // reported to optimize the loaded dex files.
+        // Note that we only need one global reporter per app.
+        // Make sure we do this before invoking app code for the first time so that we
+        // can capture the complete application startup.
+        BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
+
         // Only set up profile support if the loaded apk has the same uid as the
         // current process.
         // Currently, we do not support profiling across different apps.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index aa1b5af..b9d5907 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4770,14 +4770,16 @@
                 TemplateBindResult result) {
             boolean largeIconShown = bindLargeIcon(contentView, p);
             boolean replyIconShown = bindReplyIcon(contentView, p);
+            boolean iconContainerVisible = largeIconShown || replyIconShown;
             contentView.setViewVisibility(R.id.right_icon_container,
-                    largeIconShown || replyIconShown ? View.VISIBLE : View.GONE);
+                    iconContainerVisible ? View.VISIBLE : View.GONE);
             int marginEnd = calculateMarginEnd(largeIconShown, replyIconShown);
             contentView.setViewLayoutMarginEnd(R.id.line1, marginEnd);
             contentView.setViewLayoutMarginEnd(R.id.text, marginEnd);
             contentView.setViewLayoutMarginEnd(R.id.progress, marginEnd);
             if (result != null) {
                 result.setIconMarginEnd(marginEnd);
+                result.setRightIconContainerVisible(iconContainerVisible);
             }
         }
 
@@ -6777,7 +6779,8 @@
             mBuilder.setTextViewColorSecondary(contentView, R.id.big_text, p);
             contentView.setViewVisibility(R.id.big_text,
                     TextUtils.isEmpty(bigTextText) ? View.GONE : View.VISIBLE);
-            contentView.setBoolean(R.id.big_text, "setHasImage", mBuilder.mN.hasLargeIcon());
+            contentView.setBoolean(R.id.big_text, "setHasImage",
+                    result.isRightIconContainerVisible());
 
             return contentView;
         }
@@ -9914,6 +9917,7 @@
      */
     private static class TemplateBindResult {
         int mIconMarginEnd;
+        boolean mRightIconContainerVisible;
 
         /**
          * Get the margin end that needs to be added to any fields that may overlap
@@ -9923,9 +9927,21 @@
             return mIconMarginEnd;
         }
 
+        /**
+         * Is the icon container visible on the right size because of the reply button or the
+         * right icon.
+         */
+        public boolean isRightIconContainerVisible() {
+            return mRightIconContainerVisible;
+        }
+
         public void setIconMarginEnd(int iconMarginEnd) {
             this.mIconMarginEnd = iconMarginEnd;
         }
+
+        public void setRightIconContainerVisible(boolean iconContainerVisible) {
+            mRightIconContainerVisible = iconContainerVisible;
+        }
     }
 
     private static class StandardTemplateParams {
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 0404e80d..43e1836 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -165,9 +165,9 @@
 import android.view.accessibility.CaptioningManager;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.IAutoFillManager;
+import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.IContentCaptureManager;
 import android.view.inputmethod.InputMethodManager;
-import android.view.intelligence.ContentCaptureManager;
-import android.view.intelligence.IIntelligenceManager;
 import android.view.textclassifier.TextClassificationManager;
 import android.view.textservice.TextServicesManager;
 
@@ -1070,7 +1070,7 @@
                 if (outerContext.isContentCaptureSupported()) {
                     IBinder b = ServiceManager
                             .getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
-                    IIntelligenceManager service = IIntelligenceManager.Stub.asInterface(b);
+                    IContentCaptureManager service = IContentCaptureManager.Stub.asInterface(b);
                     return new ContentCaptureManager(outerContext, service);
                 }
                 return null;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3a97284..8e54961 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -49,6 +49,8 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.UserInfo;
 import android.graphics.Bitmap;
+import android.net.NetworkUtils;
+import android.net.PrivateDnsConnectivityChecker;
 import android.net.ProxyInfo;
 import android.net.Uri;
 import android.os.Binder;
@@ -79,6 +81,7 @@
 import android.service.restrictions.RestrictionsReceiver;
 import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
 
@@ -1121,6 +1124,64 @@
             "android.app.extra.PROVISIONING_USE_MOBILE_DATA";
 
     /**
+     * A String extra holding the provisioning trigger. It could be one of
+     * {@link #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT}, {@link #PROVISIONING_TRIGGER_QR_CODE},
+     * {@link #PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER} or {@link
+     * #PROVISIONING_TRIGGER_UNSPECIFIED}.
+     *
+     * <p>Use in an intent with action {@link
+     * #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE}.
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_PROVISIONING_TRIGGER =
+            "android.app.extra.PROVISIONING_TRIGGER";
+
+    /**
+     * A value for {@link #EXTRA_PROVISIONING_TRIGGER} indicating that the provisioning
+     * trigger has not been specified.
+     * @see #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT
+     * @see #PROVISIONING_TRIGGER_QR_CODE
+     * @see #PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER
+     * @hide
+     */
+    @SystemApi
+    public static final int PROVISIONING_TRIGGER_UNSPECIFIED = 0;
+
+    /**
+     * A value for {@link #EXTRA_PROVISIONING_TRIGGER} indicating that the provisioning
+     * trigger is cloud enrollment.
+     * @see #PROVISIONING_TRIGGER_QR_CODE
+     * @see #PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER
+     * @see #PROVISIONING_TRIGGER_UNSPECIFIED
+     * @hide
+     */
+    @SystemApi
+    public static final int PROVISIONING_TRIGGER_CLOUD_ENROLLMENT = 1;
+
+    /**
+     * A value for {@link #EXTRA_PROVISIONING_TRIGGER} indicating that the provisioning
+     * trigger is the QR code scanner.
+     * @see #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT
+     * @see #PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER
+     * @see #PROVISIONING_TRIGGER_UNSPECIFIED
+     * @hide
+     */
+    @SystemApi
+    public static final int PROVISIONING_TRIGGER_QR_CODE = 2;
+
+    /**
+     * A value for {@link #EXTRA_PROVISIONING_TRIGGER} indicating that the provisioning
+     * trigger is persistent device owner enrollment.
+     * @see #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT
+     * @see #PROVISIONING_TRIGGER_QR_CODE
+     * @see #PROVISIONING_TRIGGER_UNSPECIFIED
+     * @hide
+     */
+    @SystemApi
+    public static final int PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER = 3;
+
+    /**
      * This MIME type is used for starting the device owner provisioning.
      *
      * <p>During device owner provisioning a device admin app is set as the owner of the device.
@@ -1974,6 +2035,35 @@
     public @interface InstallUpdateCallbackErrorConstants {}
 
     /**
+     * The selected mode has been set successfully. If the mode is
+     * {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME} then it implies the supplied host is valid
+     * and reachable.
+     */
+    public static final int PRIVATE_DNS_SET_SUCCESS = 0;
+
+    /**
+     * If the {@code privateDnsHost} provided was of a valid hostname but that host was found
+     * to not support DNS-over-TLS.
+     */
+    public static final int PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING = 1;
+
+    /**
+     * General failure to set the Private DNS mode, not due to one of the reasons listed above.
+     */
+    public static final int PRIVATE_DNS_SET_ERROR_FAILURE_SETTING = 2;
+
+    /**
+     * @hide
+     */
+    @IntDef(prefix = {"PRIVATE_DNS_SET_"}, value = {
+            PRIVATE_DNS_SET_SUCCESS,
+            PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING,
+            PRIVATE_DNS_SET_ERROR_FAILURE_SETTING
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SetPrivateDnsModeResultConstants {}
+
+    /**
      * Return true if the given administrator component is currently active (enabled) in the system.
      *
      * @param admin The administrator component to check for.
@@ -9839,6 +9929,16 @@
      * Sets the global Private DNS mode and host to be used.
      * May only be called by the device owner.
      *
+     * <p>Note that in case a Private DNS resolver is specified, the method is blocking as it
+     * will perform a connectivity check to the resolver, to ensure it is valid. Because of that,
+     * the method should not be called on any thread that relates to user interaction, such as the
+     * UI thread.
+     *
+     * <p>In case a VPN is used in conjunction with Private DNS resolver, the Private DNS resolver
+     * must be reachable both from within and outside the VPN. Otherwise, the device may lose
+     * the ability to resolve hostnames as system traffic to the resolver may not go through the
+     * VPN.
+     *
      * @param admin which {@link DeviceAdminReceiver} this request is associated with.
      * @param mode Which mode to set - either {@code PRIVATE_DNS_MODE_OPPORTUNISTIC} or
      *             {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME}.
@@ -9848,6 +9948,9 @@
      * @param privateDnsHost The hostname of a server that implements DNS over TLS (RFC7858), if
      *                       {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME} was specified as the mode,
      *                       null otherwise.
+     *
+     * @return One of the values in {@link SetPrivateDnsModeResultConstants}.
+     *
      * @throws IllegalArgumentException in the following cases: if a {@code privateDnsHost} was
      * provided but the mode was not {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME}, if the mode
      * specified was {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME} but {@code privateDnsHost} does
@@ -9855,15 +9958,23 @@
      *
      * @throws SecurityException if the caller is not the device owner.
      */
-    public void setGlobalPrivateDns(@NonNull ComponentName admin,
+    public int setGlobalPrivateDns(@NonNull ComponentName admin,
             @PrivateDnsMode int mode, @Nullable String privateDnsHost) {
         throwIfParentInstance("setGlobalPrivateDns");
+
         if (mService == null) {
-            return;
+            return PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
+        }
+
+        if (mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME && !TextUtils.isEmpty(privateDnsHost)
+                && NetworkUtils.isWeaklyValidatedHostname(privateDnsHost)) {
+            if (!PrivateDnsConnectivityChecker.canConnectToPrivateDnsServer(privateDnsHost)) {
+                return PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING;
+            }
         }
 
         try {
-            mService.setGlobalPrivateDns(admin, mode, privateDnsHost);
+            return mService.setGlobalPrivateDns(admin, mode, privateDnsHost);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index fcf74ee..1148685 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -415,7 +415,7 @@
 
     boolean isMeteredDataDisabledPackageForUser(in ComponentName admin, String packageName, int userId);
 
-    void setGlobalPrivateDns(in ComponentName admin, int mode, in String privateDnsHost);
+    int setGlobalPrivateDns(in ComponentName admin, int mode, in String privateDnsHost);
     int getGlobalPrivateDnsMode(in ComponentName admin);
     String getGlobalPrivateDnsHost(in ComponentName admin);
 
diff --git a/core/java/android/app/backup/RestoreSession.java b/core/java/android/app/backup/RestoreSession.java
index 2e0f940..79925ec 100644
--- a/core/java/android/app/backup/RestoreSession.java
+++ b/core/java/android/app/backup/RestoreSession.java
@@ -143,8 +143,6 @@
      * @param packages The set of packages for which to attempt a restore.  Regardless of
      *   the contents of the actual back-end dataset named by {@code token}, only
      *   applications mentioned in this list will have their data restored.
-     *
-     * @hide
      */
     public int restoreSome(long token, RestoreObserver observer, BackupManagerMonitor monitor,
             String[] packages) {
@@ -181,8 +179,6 @@
      * @param packages The set of packages for which to attempt a restore.  Regardless of
      *   the contents of the actual back-end dataset named by {@code token}, only
      *   applications mentioned in this list will have their data restored.
-     *
-     * @hide
      */
     public int restoreSome(long token, RestoreObserver observer, String[] packages) {
         return restoreSome(token, observer, null, packages);
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 556ffa24..e84517d 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -200,12 +200,23 @@
     public static final int PRIORITY_SYNC_INITIALIZATION = 20;
 
     /**
-     * Value of {@link #getPriority} for a foreground app (overrides the supplied
+     * Value of {@link #getPriority} for a BFGS app (overrides the supplied
+     * JobInfo priority if it is smaller).
+     * @hide
+     */
+    public static final int PRIORITY_BOUND_FOREGROUND_SERVICE = 30;
+
+    /** @hide For backward compatibility. */
+    @UnsupportedAppUsage
+    public static final int PRIORITY_FOREGROUND_APP = PRIORITY_BOUND_FOREGROUND_SERVICE;
+
+    /**
+     * Value of {@link #getPriority} for a FG service app (overrides the supplied
      * JobInfo priority if it is smaller).
      * @hide
      */
     @UnsupportedAppUsage
-    public static final int PRIORITY_FOREGROUND_APP = 30;
+    public static final int PRIORITY_FOREGROUND_SERVICE = 35;
 
     /**
      * Value of {@link #getPriority} for the current top app (overrides the supplied
@@ -1593,4 +1604,29 @@
             return new JobInfo(this);
         }
     }
+
+    /**
+     * Convert a priority integer into a human readable string for debugging.
+     * @hide
+     */
+    public static String getPriorityString(int priority) {
+        switch (priority) {
+            case PRIORITY_DEFAULT:
+                return PRIORITY_DEFAULT + " [DEFAULT]";
+            case PRIORITY_SYNC_EXPEDITED:
+                return PRIORITY_SYNC_EXPEDITED + " [SYNC_EXPEDITED]";
+            case PRIORITY_SYNC_INITIALIZATION:
+                return PRIORITY_SYNC_INITIALIZATION + " [SYNC_INITIALIZATION]";
+            case PRIORITY_BOUND_FOREGROUND_SERVICE:
+                return PRIORITY_BOUND_FOREGROUND_SERVICE + " [BFGS_APP]";
+            case PRIORITY_FOREGROUND_SERVICE:
+                return PRIORITY_FOREGROUND_SERVICE + " [FGS_APP]";
+            case PRIORITY_TOP_APP:
+                return PRIORITY_TOP_APP + " [TOP_APP]";
+
+                // PRIORITY_ADJ_* are adjustments and not used as real priorities.
+                // No need to convert to strings.
+        }
+        return priority + " [UNKNOWN]";
+    }
 }
diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java
index 578a9ae..3cc56ae 100644
--- a/core/java/android/app/job/JobParameters.java
+++ b/core/java/android/app/job/JobParameters.java
@@ -47,6 +47,8 @@
     public static final int REASON_TIMEOUT = JobProtoEnums.STOP_REASON_TIMEOUT; // 3.
     /** @hide */
     public static final int REASON_DEVICE_IDLE = JobProtoEnums.STOP_REASON_DEVICE_IDLE; // 4.
+    /** @hide */
+    public static final int REASON_DEVICE_THERMAL = JobProtoEnums.STOP_REASON_DEVICE_THERMAL; // 5.
 
     /** @hide */
     public static String getReasonName(int reason) {
diff --git a/core/java/android/content/ContentInterface.java b/core/java/android/content/ContentInterface.java
new file mode 100644
index 0000000..3d732eb
--- /dev/null
+++ b/core/java/android/content/ContentInterface.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+
+/**
+ * Interface representing calls that can be made to {@link ContentProvider}
+ * instances.
+ * <p>
+ * These methods have been extracted into a general interface so that APIs can
+ * be flexible in accepting either a {@link ContentProvider}, a
+ * {@link ContentResolver}, or a {@link ContentProviderClient}.
+ */
+public interface ContentInterface {
+    public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+            @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal)
+            throws RemoteException;
+
+    public @Nullable String getType(@NonNull Uri uri) throws RemoteException;
+
+    public @Nullable String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter)
+            throws RemoteException;
+
+    public @Nullable Uri canonicalize(@NonNull Uri uri) throws RemoteException;
+
+    public @Nullable Uri uncanonicalize(@NonNull Uri uri) throws RemoteException;
+
+    public boolean refresh(@NonNull Uri uri, @Nullable Bundle args,
+            @Nullable CancellationSignal cancellationSignal) throws RemoteException;
+
+    public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues)
+            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 update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
+            @Nullable String[] selectionArgs) throws RemoteException;
+
+    public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
+            @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException;
+
+    public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
+            @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException;
+
+    public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
+            @NonNull String mimeTypeFilter, @Nullable Bundle opts,
+            @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException;
+
+    public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
+            @NonNull ArrayList<ContentProviderOperation> operations)
+            throws RemoteException, OperationApplicationException;
+
+    public @Nullable Bundle call(@NonNull String authority, @NonNull String method,
+            @Nullable String arg, @Nullable Bundle extras) throws RemoteException;
+}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index d1017c5..5a12e4e 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -51,7 +51,6 @@
 import android.os.storage.StorageManager;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -106,7 +105,7 @@
  * developer guide.</p>
  * </div>
  */
-public abstract class ContentProvider implements ComponentCallbacks2 {
+public abstract class ContentProvider implements ContentInterface, ComponentCallbacks2 {
 
     private static final String TAG = "ContentProvider";
 
@@ -325,7 +324,7 @@
         }
 
         @Override
-        public ContentProviderResult[] applyBatch(String callingPkg,
+        public ContentProviderResult[] applyBatch(String callingPkg, String authority,
                 ArrayList<ContentProviderOperation> operations)
                 throws OperationApplicationException {
             int numOperations = operations.size();
@@ -357,7 +356,8 @@
             Trace.traceBegin(TRACE_TAG_DATABASE, "applyBatch");
             final String original = setCallingPackage(callingPkg);
             try {
-                ContentProviderResult[] results = ContentProvider.this.applyBatch(operations);
+                ContentProviderResult[] results = ContentProvider.this.applyBatch(authority,
+                        operations);
                 if (results != null) {
                     for (int i = 0; i < results.length ; i++) {
                         if (userIds[i] != UserHandle.USER_CURRENT) {
@@ -445,13 +445,13 @@
         }
 
         @Override
-        public Bundle call(
-                String callingPkg, String method, @Nullable String arg, @Nullable Bundle extras) {
+        public Bundle call(String callingPkg, String authority, String method, @Nullable String arg,
+                @Nullable Bundle extras) {
             Bundle.setDefusable(extras, true);
             Trace.traceBegin(TRACE_TAG_DATABASE, "call");
             final String original = setCallingPackage(callingPkg);
             try {
-                return ContentProvider.this.call(method, arg, extras);
+                return ContentProvider.this.call(authority, method, arg, extras);
             } finally {
                 setCallingPackage(original);
                 Trace.traceEnd(TRACE_TAG_DATABASE);
@@ -589,7 +589,7 @@
                 int mode = mAppOpsManager.noteProxyOp(op, callingPkg);
                 int nonDefaultMode = mode == MODE_DEFAULT ? interpretDefaultAppOpMode(op) : mode;
                 if (mode == MODE_DEFAULT && nonDefaultMode == MODE_IGNORED) {
-                    Slog.w(TAG, "Denying access for " + callingPkg + " to " + getClass().getName()
+                    Log.w(TAG, "Denying access for " + callingPkg + " to " + getClass().getName()
                             + " (" + AppOpsManager.opToName(op)
                             + " = " + AppOpsManager.opToName(mode) + ")");
                 }
@@ -1256,6 +1256,7 @@
      *            or {@code null}.
      * @return a Cursor or {@code null}.
      */
+    @Override
     public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
             @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal) {
         queryArgs = queryArgs != null ? queryArgs : Bundle.EMPTY;
@@ -1294,6 +1295,7 @@
      * @param uri the URI to query.
      * @return a MIME type string, or {@code null} if there is no type.
      */
+    @Override
     public abstract @Nullable String getType(@NonNull Uri uri);
 
     /**
@@ -1326,6 +1328,7 @@
      * @return Return the canonical representation of <var>url</var>, or null if
      * canonicalization of that Uri is not supported.
      */
+    @Override
     public @Nullable Uri canonicalize(@NonNull Uri url) {
         return null;
     }
@@ -1344,6 +1347,7 @@
      * the data identified by the canonical representation can not be found in
      * the current environment.
      */
+    @Override
     public @Nullable Uri uncanonicalize(@NonNull Uri url) {
         return url;
     }
@@ -1370,6 +1374,7 @@
      *            canceled the refresh request.
      * @return true if the provider actually tried refreshing.
      */
+    @Override
     public boolean refresh(Uri uri, @Nullable Bundle args,
             @Nullable CancellationSignal cancellationSignal) {
         return false;
@@ -1404,6 +1409,7 @@
      *     This must not be {@code null}.
      * @return The URI for the newly inserted item.
      */
+    @Override
     public abstract @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values);
 
     /**
@@ -1421,6 +1427,7 @@
      *    This must not be {@code null}.
      * @return The number of values that were inserted.
      */
+    @Override
     public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
         int numValues = values.length;
         for (int i = 0; i < numValues; i++) {
@@ -1449,6 +1456,7 @@
      * @return The number of rows affected.
      * @throws SQLException
      */
+    @Override
     public abstract int delete(@NonNull Uri uri, @Nullable String selection,
             @Nullable String[] selectionArgs);
 
@@ -1469,6 +1477,7 @@
      * @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);
 
@@ -1605,6 +1614,7 @@
      * @see #getType(android.net.Uri)
      * @see ParcelFileDescriptor#parseMode(String)
      */
+    @Override
     public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
             @Nullable CancellationSignal signal) throws FileNotFoundException {
         return openFile(uri, mode);
@@ -1724,6 +1734,7 @@
      * @see #openFileHelper(Uri, String)
      * @see #getType(android.net.Uri)
      */
+    @Override
     public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
             @Nullable CancellationSignal signal) throws FileNotFoundException {
         return openAssetFile(uri, mode);
@@ -1790,6 +1801,7 @@
      * @see #openTypedAssetFile(Uri, String, Bundle)
      * @see ClipDescription#compareMimeTypes(String, String)
      */
+    @Override
     public @Nullable String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter) {
         return null;
     }
@@ -1906,6 +1918,7 @@
      * @see #openAssetFile(Uri, String)
      * @see ClipDescription#compareMimeTypes(String, String)
      */
+    @Override
     public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
             @NonNull String mimeTypeFilter, @Nullable Bundle opts,
             @Nullable CancellationSignal signal) throws FileNotFoundException {
@@ -2060,6 +2073,13 @@
      * @throws OperationApplicationException thrown if any operation fails.
      * @see ContentProviderOperation#apply
      */
+    @Override
+    public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
+            @NonNull ArrayList<ContentProviderOperation> operations)
+                    throws OperationApplicationException {
+        return applyBatch(operations);
+    }
+
     public @NonNull ContentProviderResult[] applyBatch(
             @NonNull ArrayList<ContentProviderOperation> operations)
                     throws OperationApplicationException {
@@ -2089,6 +2109,12 @@
      * @return provider-defined return value.  May be {@code null}, which is also
      *   the default for providers which don't implement any call methods.
      */
+    @Override
+    public @Nullable Bundle call(@NonNull String authority, @NonNull String method,
+            @Nullable String arg, @Nullable Bundle extras) {
+        return call(method, arg, extras);
+    }
+
     public @Nullable Bundle call(@NonNull String method, @Nullable String arg,
             @Nullable Bundle extras) {
         return null;
@@ -2134,6 +2160,19 @@
         writer.println("nothing to dump");
     }
 
+    private void validateIncomingAuthority(String authority) throws SecurityException {
+        if (!matchesOurAuthorities(getAuthorityWithoutUserId(authority))) {
+            String message = "The authority " + authority + " does not match the one of the "
+                    + "contentProvider: ";
+            if (mAuthority != null) {
+                message += mAuthority;
+            } else {
+                message += Arrays.toString(mAuthorities);
+            }
+            throw new SecurityException(message);
+        }
+    }
+
     /** @hide */
     @VisibleForTesting
     public Uri validateIncomingUri(Uri uri) throws SecurityException {
@@ -2145,16 +2184,7 @@
                         + mContext.getUserId() + " with a uri belonging to user " + userId);
             }
         }
-        if (!matchesOurAuthorities(getAuthorityWithoutUserId(auth))) {
-            String message = "The authority of the uri " + uri + " does not match the one of the "
-                    + "contentProvider: ";
-            if (mAuthority != null) {
-                message += mAuthority;
-            } else {
-                message += Arrays.toString(mAuthorities);
-            }
-            throw new SecurityException(message);
-        }
+        validateIncomingAuthority(auth);
 
         // Normalize the path by removing any empty path segments, which can be
         // a source of security issues.
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index d315f49..0b5bdb5 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -16,8 +16,12 @@
 
 package android.content;
 
+import android.annotation.DurationMillisLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetFileDescriptor;
 import android.database.CrossProcessCursorWrapper;
@@ -65,7 +69,7 @@
  * on the ContentProviderClient those calls are made from until you are finished
  * with the data they have returned.
  */
-public class ContentProviderClient implements AutoCloseable {
+public class ContentProviderClient implements ContentInterface, AutoCloseable {
     private static final String TAG = "ContentProviderClient";
 
     @GuardedBy("ContentProviderClient.class")
@@ -76,6 +80,7 @@
     private final IContentProvider mContentProvider;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final String mPackageName;
+    private final String mAuthority;
     private final boolean mStable;
 
     private final AtomicBoolean mClosed = new AtomicBoolean();
@@ -86,19 +91,39 @@
 
     /** {@hide} */
     @VisibleForTesting
-    public ContentProviderClient(
-            ContentResolver contentResolver, IContentProvider contentProvider, boolean stable) {
+    public ContentProviderClient(ContentResolver contentResolver, IContentProvider contentProvider,
+            boolean stable) {
+        // Only used for testing, so use a fake authority
+        this(contentResolver, contentProvider, "unknown", stable);
+    }
+
+    /** {@hide} */
+    public ContentProviderClient(ContentResolver contentResolver, IContentProvider contentProvider,
+            String authority, boolean stable) {
         mContentResolver = contentResolver;
         mContentProvider = contentProvider;
         mPackageName = contentResolver.mPackageName;
 
+        mAuthority = authority;
         mStable = stable;
 
         mCloseGuard.open("close");
     }
 
-    /** {@hide} */
-    public void setDetectNotResponding(long timeoutMillis) {
+    /**
+     * Configure this client to automatically detect and kill the remote
+     * provider when an "application not responding" event is detected.
+     *
+     * @param timeoutMillis the duration for which a pending call is allowed
+     *            block before the remote provider is considered to be
+     *            unresponsive. Set to {@code 0} to allow pending calls to block
+     *            indefinitely with no action taken.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.REMOVE_TASKS)
+    public void setDetectNotResponding(@DurationMillisLong long timeoutMillis) {
         synchronized (ContentProviderClient.class) {
             mAnrTimeout = timeoutMillis;
 
@@ -153,6 +178,7 @@
     }
 
     /** See {@link ContentProvider#query ContentProvider.query} */
+    @Override
     public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
             Bundle queryArgs, @Nullable CancellationSignal cancellationSignal)
                     throws RemoteException {
@@ -183,6 +209,7 @@
     }
 
     /** See {@link ContentProvider#getType ContentProvider.getType} */
+    @Override
     public @Nullable String getType(@NonNull Uri url) throws RemoteException {
         Preconditions.checkNotNull(url, "url");
 
@@ -200,6 +227,7 @@
     }
 
     /** See {@link ContentProvider#getStreamTypes ContentProvider.getStreamTypes} */
+    @Override
     public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter)
             throws RemoteException {
         Preconditions.checkNotNull(url, "url");
@@ -219,6 +247,7 @@
     }
 
     /** See {@link ContentProvider#canonicalize} */
+    @Override
     public final @Nullable Uri canonicalize(@NonNull Uri url) throws RemoteException {
         Preconditions.checkNotNull(url, "url");
 
@@ -236,6 +265,7 @@
     }
 
     /** See {@link ContentProvider#uncanonicalize} */
+    @Override
     public final @Nullable Uri uncanonicalize(@NonNull Uri url) throws RemoteException {
         Preconditions.checkNotNull(url, "url");
 
@@ -253,6 +283,7 @@
     }
 
     /** See {@link ContentProvider#refresh} */
+    @Override
     public boolean refresh(Uri url, @Nullable Bundle args,
             @Nullable CancellationSignal cancellationSignal) throws RemoteException {
         Preconditions.checkNotNull(url, "url");
@@ -277,6 +308,7 @@
     }
 
     /** See {@link ContentProvider#insert ContentProvider.insert} */
+    @Override
     public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues)
             throws RemoteException {
         Preconditions.checkNotNull(url, "url");
@@ -295,6 +327,7 @@
     }
 
     /** See {@link ContentProvider#bulkInsert ContentProvider.bulkInsert} */
+    @Override
     public int bulkInsert(@NonNull Uri url, @NonNull ContentValues[] initialValues)
             throws RemoteException {
         Preconditions.checkNotNull(url, "url");
@@ -314,6 +347,7 @@
     }
 
     /** See {@link ContentProvider#delete ContentProvider.delete} */
+    @Override
     public int delete(@NonNull Uri url, @Nullable String selection,
             @Nullable String[] selectionArgs) throws RemoteException {
         Preconditions.checkNotNull(url, "url");
@@ -332,6 +366,7 @@
     }
 
     /** See {@link ContentProvider#update ContentProvider.update} */
+    @Override
     public int update(@NonNull Uri url, @Nullable ContentValues values, @Nullable String selection,
             @Nullable String[] selectionArgs) throws RemoteException {
         Preconditions.checkNotNull(url, "url");
@@ -368,6 +403,7 @@
      * you use the {@link ContentResolver#openFileDescriptor
      * ContentResolver.openFileDescriptor} API instead.
      */
+    @Override
     public @Nullable ParcelFileDescriptor openFile(@NonNull Uri url, @NonNull String mode,
             @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
         Preconditions.checkNotNull(url, "url");
@@ -411,6 +447,7 @@
      * you use the {@link ContentResolver#openAssetFileDescriptor
      * ContentResolver.openAssetFileDescriptor} API instead.
      */
+    @Override
     public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri url, @NonNull String mode,
             @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
         Preconditions.checkNotNull(url, "url");
@@ -446,8 +483,15 @@
     public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
             @NonNull String mimeType, @Nullable Bundle opts, @Nullable CancellationSignal signal)
                     throws RemoteException, FileNotFoundException {
+        return openTypedAssetFile(uri, mimeType, opts, signal);
+    }
+
+    @Override
+    public final @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
+            @NonNull String mimeTypeFilter, @Nullable Bundle opts,
+            @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
         Preconditions.checkNotNull(uri, "uri");
-        Preconditions.checkNotNull(mimeType, "mimeType");
+        Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
 
         beforeRemote();
         try {
@@ -458,7 +502,7 @@
                 signal.setRemote(remoteSignal);
             }
             return mContentProvider.openTypedAssetFile(
-                    mPackageName, uri, mimeType, opts, remoteSignal);
+                    mPackageName, uri, mimeTypeFilter, opts, remoteSignal);
         } catch (DeadObjectException e) {
             if (!mStable) {
                 mContentResolver.unstableProviderDied(mContentProvider);
@@ -472,12 +516,20 @@
     /** See {@link ContentProvider#applyBatch ContentProvider.applyBatch} */
     public @NonNull ContentProviderResult[] applyBatch(
             @NonNull ArrayList<ContentProviderOperation> operations)
-                    throws RemoteException, OperationApplicationException {
+            throws RemoteException, OperationApplicationException {
+        return applyBatch(mAuthority, operations);
+    }
+
+    /** See {@link ContentProvider#applyBatch ContentProvider.applyBatch} */
+    @Override
+    public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
+            @NonNull ArrayList<ContentProviderOperation> operations)
+            throws RemoteException, OperationApplicationException {
         Preconditions.checkNotNull(operations, "operations");
 
         beforeRemote();
         try {
-            return mContentProvider.applyBatch(mPackageName, operations);
+            return mContentProvider.applyBatch(mPackageName, authority, operations);
         } catch (DeadObjectException e) {
             if (!mStable) {
                 mContentResolver.unstableProviderDied(mContentProvider);
@@ -491,11 +543,19 @@
     /** See {@link ContentProvider#call(String, String, Bundle)} */
     public @Nullable Bundle call(@NonNull String method, @Nullable String arg,
             @Nullable Bundle extras) throws RemoteException {
+        return call(mAuthority, method, arg, extras);
+    }
+
+    /** See {@link ContentProvider#call(String, String, Bundle)} */
+    @Override
+    public @Nullable Bundle call(@NonNull String authority, @NonNull String method,
+            @Nullable String arg, @Nullable Bundle extras) throws RemoteException {
+        Preconditions.checkNotNull(authority, "authority");
         Preconditions.checkNotNull(method, "method");
 
         beforeRemote();
         try {
-            return mContentProvider.call(mPackageName, method, arg, extras);
+            return mContentProvider.call(mPackageName, authority, method, arg, 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 6bede13..ca657b1 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -174,13 +174,15 @@
                 {
                     data.enforceInterface(IContentProvider.descriptor);
                     String callingPkg = data.readString();
+                    String authority = data.readString();
                     final int numOperations = data.readInt();
                     final ArrayList<ContentProviderOperation> operations =
                             new ArrayList<>(numOperations);
                     for (int i = 0; i < numOperations; i++) {
                         operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data));
                     }
-                    final ContentProviderResult[] results = applyBatch(callingPkg, operations);
+                    final ContentProviderResult[] results = applyBatch(callingPkg, authority,
+                            operations);
                     reply.writeNoException();
                     reply.writeTypedArray(results, 0);
                     return true;
@@ -267,11 +269,12 @@
                     data.enforceInterface(IContentProvider.descriptor);
 
                     String callingPkg = data.readString();
+                    String authority = data.readString();
                     String method = data.readString();
                     String stringArg = data.readString();
                     Bundle args = data.readBundle();
 
-                    Bundle responseBundle = call(callingPkg, method, stringArg, args);
+                    Bundle responseBundle = call(callingPkg, authority, method, stringArg, args);
 
                     reply.writeNoException();
                     reply.writeBundle(responseBundle);
@@ -507,7 +510,7 @@
     }
 
     @Override
-    public ContentProviderResult[] applyBatch(String callingPkg,
+    public ContentProviderResult[] applyBatch(String callingPkg, String authority,
             ArrayList<ContentProviderOperation> operations)
                     throws RemoteException, OperationApplicationException {
         Parcel data = Parcel.obtain();
@@ -515,6 +518,7 @@
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
             data.writeString(callingPkg);
+            data.writeString(authority);
             data.writeInt(operations.size());
             for (ContentProviderOperation operation : operations) {
                 operation.writeToParcel(data, 0);
@@ -636,14 +640,15 @@
     }
 
     @Override
-    public Bundle call(String callingPkg, String method, String request, Bundle args)
-            throws RemoteException {
+    public Bundle call(String callingPkg, String authority, String method, String request,
+            Bundle args) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         try {
             data.writeInterfaceToken(IContentProvider.descriptor);
 
             data.writeString(callingPkg);
+            data.writeString(authority);
             data.writeString(method);
             data.writeString(request);
             data.writeBundle(args);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 7d5202d..da65941 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -52,7 +52,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
 import android.text.TextUtils;
@@ -88,7 +87,7 @@
  * <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
  * developer guide.</p>
  */
-public abstract class ContentResolver {
+public abstract class ContentResolver implements ContentInterface {
     /**
      * Enables logic that supports deprecation of {@code _data} columns,
      * typically by replacing values with fake paths that the OS then offers to
@@ -655,6 +654,7 @@
      * using the content:// scheme.
      * @return A MIME type for the content, or null if the URL is invalid or the type is unknown
      */
+    @Override
     public final @Nullable String getType(@NonNull Uri url) {
         Preconditions.checkNotNull(url, "url");
 
@@ -708,6 +708,7 @@
      * data streams that match the given mimeTypeFilter.  If there are none,
      * null is returned.
      */
+    @Override
     public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter) {
         Preconditions.checkNotNull(url, "url");
         Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
@@ -835,6 +836,7 @@
      * @return A Cursor object, which is positioned before the first entry, or null
      * @see Cursor
      */
+    @Override
     public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
             @Nullable String[] projection, @Nullable Bundle queryArgs,
             @Nullable CancellationSignal cancellationSignal) {
@@ -935,6 +937,7 @@
      *
      * @see #uncanonicalize
      */
+    @Override
     public final @Nullable Uri canonicalize(@NonNull Uri url) {
         Preconditions.checkNotNull(url, "url");
         IContentProvider provider = acquireProvider(url);
@@ -971,6 +974,7 @@
      *
      * @see #canonicalize
      */
+    @Override
     public final @Nullable Uri uncanonicalize(@NonNull Uri url) {
         Preconditions.checkNotNull(url, "url");
         IContentProvider provider = acquireProvider(url);
@@ -1005,6 +1009,7 @@
      *            canceled the refresh request.
      * @return true if the provider actually tried refreshing.
      */
+    @Override
     public final boolean refresh(@NonNull Uri url, @Nullable Bundle args,
             @Nullable CancellationSignal cancellationSignal) {
         Preconditions.checkNotNull(url, "url");
@@ -1116,6 +1121,12 @@
         }
     }
 
+    @Override
+    public final @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
+            @Nullable CancellationSignal signal) throws FileNotFoundException {
+        return openFileDescriptor(uri, mode, signal);
+    }
+
     /**
      * Open a raw file descriptor to access data under a URI.  This
      * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the
@@ -1221,6 +1232,12 @@
         throw new FileNotFoundException("Not a whole file");
     }
 
+    @Override
+    public final @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
+            @Nullable CancellationSignal signal) throws FileNotFoundException {
+        return openAssetFileDescriptor(uri, mode, signal);
+    }
+
     /**
      * Open a raw file descriptor to access data under a URI.  This
      * interacts with the underlying {@link ContentProvider#openAssetFile}
@@ -1425,6 +1442,13 @@
         }
     }
 
+    @Override
+    public final @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
+            @NonNull String mimeTypeFilter, @Nullable Bundle opts,
+            @Nullable CancellationSignal signal) throws FileNotFoundException {
+        return openTypedAssetFileDescriptor(uri, mimeTypeFilter, opts, signal);
+    }
+
     /**
      * Open a raw file descriptor to access (potentially type transformed)
      * data from a "content:" URI.  This interacts with the underlying
@@ -1634,6 +1658,7 @@
      *               the field. Passing an empty ContentValues will create an empty row.
      * @return the URL of the newly created row.
      */
+    @Override
     public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
                 @Nullable ContentValues values) {
         Preconditions.checkNotNull(url, "url");
@@ -1672,6 +1697,7 @@
      * @throws RemoteException thrown if a RemoteException is encountered while attempting
      *   to communicate with a remote provider.
      */
+    @Override
     public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
             @NonNull ArrayList<ContentProviderOperation> operations)
                     throws RemoteException, OperationApplicationException {
@@ -1698,6 +1724,7 @@
      *               the field. Passing null will create an empty row.
      * @return the number of newly created rows.
      */
+    @Override
     public final int bulkInsert(@RequiresPermission.Write @NonNull Uri url,
                 @NonNull ContentValues[] values) {
         Preconditions.checkNotNull(url, "url");
@@ -1731,6 +1758,7 @@
                     (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) {
         Preconditions.checkNotNull(url, "url");
@@ -1766,6 +1794,7 @@
      * @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) {
@@ -1805,14 +1834,20 @@
      */
     public final @Nullable Bundle call(@NonNull Uri uri, @NonNull String method,
             @Nullable String arg, @Nullable Bundle extras) {
-        Preconditions.checkNotNull(uri, "uri");
+        return call(uri.getAuthority(), method, arg, extras);
+    }
+
+    @Override
+    public final @Nullable Bundle call(@NonNull String authority, @NonNull String method,
+            @Nullable String arg, @Nullable Bundle extras) {
+        Preconditions.checkNotNull(authority, "authority");
         Preconditions.checkNotNull(method, "method");
-        IContentProvider provider = acquireProvider(uri);
+        IContentProvider provider = acquireProvider(authority);
         if (provider == null) {
-            throw new IllegalArgumentException("Unknown URI " + uri);
+            throw new IllegalArgumentException("Unknown authority " + authority);
         }
         try {
-            final Bundle res = provider.call(mPackageName, method, arg, extras);
+            final Bundle res = provider.call(mPackageName, authority, method, arg, extras);
             Bundle.setDefusable(res, true);
             return res;
         } catch (RemoteException e) {
@@ -1918,7 +1953,7 @@
         Preconditions.checkNotNull(uri, "uri");
         IContentProvider provider = acquireProvider(uri);
         if (provider != null) {
-            return new ContentProviderClient(this, provider, true);
+            return new ContentProviderClient(this, provider, uri.getAuthority(), true);
         }
         return null;
     }
@@ -1939,7 +1974,7 @@
         Preconditions.checkNotNull(name, "name");
         IContentProvider provider = acquireProvider(name);
         if (provider != null) {
-            return new ContentProviderClient(this, provider, true);
+            return new ContentProviderClient(this, provider, name, true);
         }
 
         return null;
@@ -1966,7 +2001,7 @@
         Preconditions.checkNotNull(uri, "uri");
         IContentProvider provider = acquireUnstableProvider(uri);
         if (provider != null) {
-            return new ContentProviderClient(this, provider, false);
+            return new ContentProviderClient(this, provider, uri.getAuthority(), false);
         }
 
         return null;
@@ -1993,7 +2028,7 @@
         Preconditions.checkNotNull(name, "name");
         IContentProvider provider = acquireUnstableProvider(name);
         if (provider != null) {
-            return new ContentProviderClient(this, provider, false);
+            return new ContentProviderClient(this, provider, name, false);
         }
 
         return null;
@@ -3248,10 +3283,10 @@
     }
 
     /** {@hide} */
-    public static Bitmap loadThumbnail(@NonNull ContentProviderClient client, @NonNull Uri uri,
+    public static Bitmap loadThumbnail(@NonNull ContentInterface content, @NonNull Uri uri,
             @NonNull Size size, @Nullable CancellationSignal signal, int allocator)
             throws IOException {
-        Objects.requireNonNull(client);
+        Objects.requireNonNull(content);
         Objects.requireNonNull(uri);
         Objects.requireNonNull(size);
 
@@ -3260,7 +3295,7 @@
         opts.putParcelable(EXTRA_SIZE, Point.convert(size));
 
         return ImageDecoder.decodeBitmap(ImageDecoder.createSource(() -> {
-            return client.openTypedAssetFileDescriptor(uri, "image/*", opts, signal);
+            return content.openTypedAssetFile(uri, "image/*", opts, signal);
         }), (ImageDecoder decoder, ImageInfo info, Source source) -> {
             decoder.setAllocator(allocator);
 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index e2c7b85..d7d3cb5 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3939,13 +3939,12 @@
     public static final String AUTOFILL_MANAGER_SERVICE = "autofill";
 
     /**
-     * Official published name of the smart suggestions service.
+     * Official published name of the content capture service.
      *
      * @hide
      * @see #getSystemService(String)
      */
-    // TODO(b/111276913): rename string (will require SELinux change first)
-    public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "intelligence";
+    public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
 
     /**
      * Use with {@link #getSystemService(String)} to access the
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 044ed61..0427c2f 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -60,13 +60,28 @@
     public AssetFileDescriptor openAssetFile(
             String callingPkg, Uri url, String mode, ICancellationSignal signal)
             throws RemoteException, FileNotFoundException;
-    public ContentProviderResult[] applyBatch(String callingPkg,
+
+    @Deprecated
+    public default ContentProviderResult[] applyBatch(String callingPkg,
             ArrayList<ContentProviderOperation> operations)
-                    throws RemoteException, OperationApplicationException;
+                    throws RemoteException, OperationApplicationException {
+        return applyBatch(callingPkg, "unknown", operations);
+    }
+
+    public ContentProviderResult[] applyBatch(String callingPkg, String authority,
+            ArrayList<ContentProviderOperation> operations)
+            throws RemoteException, OperationApplicationException;
+
+    @Deprecated
     @UnsupportedAppUsage
-    public Bundle call(
-            String callingPkg, String method, @Nullable String arg, @Nullable Bundle extras)
-            throws RemoteException;
+    public default Bundle call(String callingPkg, String method,
+            @Nullable String arg, @Nullable Bundle extras) throws RemoteException {
+        return call(callingPkg, "unknown", method, arg, extras);
+    }
+
+    public Bundle call(String callingPkg, String authority, String method,
+            @Nullable String arg, @Nullable Bundle extras) throws RemoteException;
+
     public ICancellationSignal createCancellationSignal() throws RemoteException;
 
     public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c2907d2..b6f9d15 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -5242,6 +5242,7 @@
 
     /**
      * Optional CharSequence extra to provide a search query.
+     * The format of this query is dependent on the receiving application.
      *
      * <p>Applicable to {@link Intent} with actions:
      * <ul>
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b7df2bf..f40be84 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2687,6 +2687,16 @@
             "android.software.device_id_attestation";
 
     /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has
+     * the requisite kernel support for multinetworking-capable IPsec tunnels.
+     *
+     * <p>This feature implies that the device supports XFRM Interfaces (CONFIG_XFRM_INTERFACE), or
+     * VTIs with kernel patches allowing updates of output/set mark via UPDSA.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_IPSEC_TUNNELS = "android.software.ipsec_tunnels";
+
+    /**
      * Extra field name for the URI to a verification file. Passed to a package
      * verifier.
      *
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index ff58c75..eb3414d2 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -152,5 +152,24 @@
             Slog.w(TAG, "setActiveUser(): Service not connected");
         }
     }
+
+    /**
+     * Reset the timeout when user authenticates with strong auth (e.g. PIN, pattern or password)
+     *
+     * @param token an opaque token returned by password confirmation.
+     * @hide
+     */
+    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+    public void resetTimeout(byte[] token) {
+        if (mService != null) {
+            try {
+                mService.resetTimeout(token);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        } else {
+            Slog.w(TAG, "resetTimeout(): Service not connected");
+        }
+    }
 }
 
diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl
index 53a0761..de828f2 100644
--- a/core/java/android/hardware/biometrics/IBiometricService.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricService.aidl
@@ -48,4 +48,7 @@
     // Notify BiometricService when <Biometric>Service is ready to start the prepared client.
     // Client lifecycle is still managed in <Biometric>Service.
     void onReadyForAuthentication(int cookie, boolean requireConfirmation, int userId);
+
+    // Reset the timeout when user authenticates with strong auth (e.g. PIN, pattern or password)
+    void resetTimeout(in byte [] token);
 }
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 0bdfca7..0c44a56 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
@@ -79,6 +80,7 @@
         mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0;
         mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED;
         mNetworkSpecifier = null;
+        mTransportInfo = null;
         mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
         mUids = null;
         mEstablishingVpnAppUid = INVALID_UID;
@@ -95,6 +97,7 @@
         mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
         mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
         mNetworkSpecifier = nc.mNetworkSpecifier;
+        mTransportInfo = nc.mTransportInfo;
         mSignalStrength = nc.mSignalStrength;
         setUids(nc.mUids); // Will make the defensive copy
         mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid;
@@ -874,6 +877,7 @@
     }
 
     private NetworkSpecifier mNetworkSpecifier = null;
+    private TransportInfo mTransportInfo = null;
 
     /**
      * Sets the optional bearer specific network specifier.
@@ -899,6 +903,19 @@
     }
 
     /**
+     * Sets the optional transport specific information.
+     *
+     * @param transportInfo A concrete, parcelable framework class that extends
+     * {@link TransportInfo}.
+     * @return This NetworkCapabilities instance, to facilitate chaining.
+     * @hide
+     */
+    public NetworkCapabilities setTransportInfo(TransportInfo transportInfo) {
+        mTransportInfo = transportInfo;
+        return this;
+    }
+
+    /**
      * Gets the optional bearer specific network specifier.
      *
      * @return The optional {@link NetworkSpecifier} specifying the bearer specific network
@@ -910,6 +927,19 @@
         return mNetworkSpecifier;
     }
 
+    /**
+     * Returns a transport-specific information container. The application may cast this
+     * container to a concrete sub-class based on its knowledge of the network request. The
+     * application should be able to deal with a {@code null} return value or an invalid case,
+     * e.g. use {@code instanceof} operation to verify expected type.
+     *
+     * @return A concrete implementation of the {@link TransportInfo} class or null if not
+     * available for the network.
+     */
+    @Nullable public TransportInfo getTransportInfo() {
+        return mTransportInfo;
+    }
+
     private void combineSpecifiers(NetworkCapabilities nc) {
         if (mNetworkSpecifier != null && !mNetworkSpecifier.equals(nc.mNetworkSpecifier)) {
             throw new IllegalStateException("Can't combine two networkSpecifiers");
@@ -926,6 +956,17 @@
         return Objects.equals(mNetworkSpecifier, nc.mNetworkSpecifier);
     }
 
+    private void combineTransportInfos(NetworkCapabilities nc) {
+        if (mTransportInfo != null && !mTransportInfo.equals(nc.mTransportInfo)) {
+            throw new IllegalStateException("Can't combine two TransportInfos");
+        }
+        setTransportInfo(nc.mTransportInfo);
+    }
+
+    private boolean equalsTransportInfo(NetworkCapabilities nc) {
+        return Objects.equals(mTransportInfo, nc.mTransportInfo);
+    }
+
     /**
      * Magic value that indicates no signal strength provided. A request specifying this value is
      * always satisfied.
@@ -1238,6 +1279,7 @@
         combineTransportTypes(nc);
         combineLinkBandwidths(nc);
         combineSpecifiers(nc);
+        combineTransportInfos(nc);
         combineSignalStrength(nc);
         combineUids(nc);
         combineSSIDs(nc);
@@ -1347,6 +1389,7 @@
                 && equalsLinkBandwidths(that)
                 && equalsSignalStrength(that)
                 && equalsSpecifier(that)
+                && equalsTransportInfo(that)
                 && equalsUids(that)
                 && equalsSSID(that));
     }
@@ -1364,7 +1407,8 @@
                 + Objects.hashCode(mNetworkSpecifier) * 23
                 + (mSignalStrength * 29)
                 + Objects.hashCode(mUids) * 31
-                + Objects.hashCode(mSSID) * 37;
+                + Objects.hashCode(mSSID) * 37
+                + Objects.hashCode(mTransportInfo) * 41;
     }
 
     @Override
@@ -1379,6 +1423,7 @@
         dest.writeInt(mLinkUpBandwidthKbps);
         dest.writeInt(mLinkDownBandwidthKbps);
         dest.writeParcelable((Parcelable) mNetworkSpecifier, flags);
+        dest.writeParcelable((Parcelable) mTransportInfo, flags);
         dest.writeInt(mSignalStrength);
         dest.writeArraySet(mUids);
         dest.writeString(mSSID);
@@ -1396,6 +1441,7 @@
                 netCap.mLinkUpBandwidthKbps = in.readInt();
                 netCap.mLinkDownBandwidthKbps = in.readInt();
                 netCap.mNetworkSpecifier = in.readParcelable(null);
+                netCap.mTransportInfo = in.readParcelable(null);
                 netCap.mSignalStrength = in.readInt();
                 netCap.mUids = (ArraySet<UidRange>) in.readArraySet(
                         null /* ClassLoader, null for default */);
@@ -1435,6 +1481,9 @@
         if (mNetworkSpecifier != null) {
             sb.append(" Specifier: <").append(mNetworkSpecifier).append(">");
         }
+        if (mTransportInfo != null) {
+            sb.append(" TransportInfo: <").append(mTransportInfo).append(">");
+        }
         if (hasSignalStrength()) {
             sb.append(" SignalStrength: ").append(mSignalStrength);
         }
@@ -1501,6 +1550,9 @@
         if (mNetworkSpecifier != null) {
             proto.write(NetworkCapabilitiesProto.NETWORK_SPECIFIER, mNetworkSpecifier.toString());
         }
+        if (mTransportInfo != null) {
+            // TODO b/120653863: write transport-specific info to proto?
+        }
 
         proto.write(NetworkCapabilitiesProto.CAN_REPORT_SIGNAL_STRENGTH, hasSignalStrength());
         proto.write(NetworkCapabilitiesProto.SIGNAL_STRENGTH, mSignalStrength);
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 5447f59..a00b9a3 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -44,6 +44,7 @@
  *
  * @hide
  */
+// @NotThreadSafe
 public class NetworkStats implements Parcelable {
     private static final String TAG = "NetworkStats";
     /** {@link #iface} value when interface details unavailable. */
@@ -443,6 +444,26 @@
         return entry;
     }
 
+    /**
+     * If @{code dest} is not equal to @{code src}, copy entry from index @{code src} to index
+     * @{code dest}.
+     */
+    private void maybeCopyEntry(int dest, int src) {
+        if (dest == src) return;
+        iface[dest] = iface[src];
+        uid[dest] = uid[src];
+        set[dest] = set[src];
+        tag[dest] = tag[src];
+        metered[dest] = metered[src];
+        roaming[dest] = roaming[src];
+        defaultNetwork[dest] = defaultNetwork[src];
+        rxBytes[dest] = rxBytes[src];
+        rxPackets[dest] = rxPackets[src];
+        txBytes[dest] = txBytes[src];
+        txPackets[dest] = txPackets[src];
+        operations[dest] = operations[src];
+    }
+
     public long getElapsedRealtime() {
         return elapsedRealtime;
     }
@@ -941,21 +962,18 @@
     }
 
     /**
-     * Return all rows except those attributed to the requested UID; doesn't
-     * mutate the original structure.
+     * Remove all rows that match one of specified UIDs.
      */
-    public NetworkStats withoutUids(int[] uids) {
-        final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
-
-        Entry entry = new Entry();
+    public void removeUids(int[] uids) {
+        int nextOutputEntry = 0;
         for (int i = 0; i < size; i++) {
-            entry = getValues(i, entry);
-            if (!ArrayUtils.contains(uids, entry.uid)) {
-                stats.addValues(entry);
+            if (!ArrayUtils.contains(uids, uid[i])) {
+                maybeCopyEntry(nextOutputEntry, i);
+                nextOutputEntry++;
             }
         }
 
-        return stats;
+        size = nextOutputEntry;
     }
 
     /**
diff --git a/core/java/android/net/PrivateDnsConnectivityChecker.java b/core/java/android/net/PrivateDnsConnectivityChecker.java
new file mode 100644
index 0000000..cfd458c
--- /dev/null
+++ b/core/java/android/net/PrivateDnsConnectivityChecker.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.NonNull;
+import android.util.Log;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+/**
+ * Class for testing connectivity to DNS-over-TLS servers.
+ * {@hide}
+ */
+public class PrivateDnsConnectivityChecker {
+    private static final String TAG = "NetworkUtils";
+
+    private static final int PRIVATE_DNS_PORT = 853;
+    private static final int CONNECTION_TIMEOUT_MS = 5000;
+
+    private PrivateDnsConnectivityChecker() { }
+
+    /**
+     * checks that a provided host can perform a TLS handshake on port 853.
+     * @param hostname host to connect to.
+     */
+    public static boolean canConnectToPrivateDnsServer(@NonNull String hostname) {
+        final SocketFactory factory = SSLSocketFactory.getDefault();
+        TrafficStats.setThreadStatsTag(TrafficStats.TAG_SYSTEM_APP);
+
+        try (SSLSocket socket = (SSLSocket) factory.createSocket()) {
+            socket.setSoTimeout(CONNECTION_TIMEOUT_MS);
+            socket.connect(new InetSocketAddress(hostname, PRIVATE_DNS_PORT));
+            if (!socket.isConnected()) {
+                Log.w(TAG, String.format("Connection to %s failed.", hostname));
+                return false;
+            }
+            socket.startHandshake();
+            Log.w(TAG, String.format("TLS handshake to %s succeeded.", hostname));
+            return true;
+        } catch (IOException e) {
+            Log.w(TAG, String.format("TLS handshake to %s failed.", hostname), e);
+            return false;
+        }
+    }
+}
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.aidl b/core/java/android/net/TransportInfo.java
similarity index 69%
copy from core/java/android/view/intelligence/ContentCaptureEvent.aidl
copy to core/java/android/net/TransportInfo.java
index c66a6cb..b78d3fe 100644
--- a/core/java/android/view/intelligence/ContentCaptureEvent.aidl
+++ b/core/java/android/net/TransportInfo.java
@@ -14,6 +14,12 @@
  * limitations under the License.
  */
 
-package android.view.intelligence;
+package android.net;
 
-parcelable ContentCaptureEvent;
+/**
+ * A container for transport-specific capabilities which is returned by
+ * {@link NetworkCapabilities#getTransportInfo()}. Specific networks
+ * may provide concrete implementations of this interface.
+ */
+public interface TransportInfo {
+}
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index d09f33b..af3ee09 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -374,11 +374,12 @@
     public abstract String toString();
 
     /**
-     * Return a string representation of the URI that is safe to print
-     * to logs and other places where PII should be avoided.
-     * @hide
+     * Return a string representation of this URI that has common forms of PII redacted,
+     * making it safer to use for logging purposes.  For example, {@code tel:800-466-4411} is
+     * returned as {@code tel:xxx-xxx-xxxx} and {@code http://example.com/path/to/item/} is
+     * returned as {@code http://example.com/...}.
+     * @return the common forms PII redacted string of this URI
      */
-    @UnsupportedAppUsage
     public String toSafeString() {
         String scheme = getScheme();
         String ssp = getSchemeSpecificPart();
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 8cafbde..7abe913 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -16,14 +16,13 @@
 
 package android.os;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.AssetManager;
 import android.opengl.EGL14;
-import android.os.Build;
-import android.os.SystemProperties;
 import android.provider.Settings;
 import android.util.Log;
 
@@ -37,6 +36,11 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /** @hide */
 public class GraphicsEnvironment {
@@ -67,7 +71,7 @@
      */
     public void setup(Context context, Bundle coreSettings) {
         setupGpuLayers(context, coreSettings);
-        setupAngle(context, coreSettings);
+        setupAngle(context, context.getPackageName());
         chooseDriver(context, coreSettings);
     }
 
@@ -192,24 +196,101 @@
         setLayerPaths(mClassLoader, layerPaths);
     }
 
+    enum OpenGlDriverChoice {
+        DEFAULT,
+        NATIVE,
+        ANGLE
+    }
+
+    private static final Map<OpenGlDriverChoice, String> sDriverMap = buildMap();
+    private static Map<OpenGlDriverChoice, String> buildMap() {
+        Map<OpenGlDriverChoice, String> map = new HashMap<>();
+        map.put(OpenGlDriverChoice.DEFAULT, "default");
+        map.put(OpenGlDriverChoice.ANGLE, "angle");
+        map.put(OpenGlDriverChoice.NATIVE, "native");
+
+        return map;
+    }
+
+
+    private static List<String> getGlobalSettingsString(Context context, String globalSetting) {
+        List<String> valueList = null;
+        ContentResolver contentResolver = context.getContentResolver();
+        String settingsValue = Settings.Global.getString(contentResolver, globalSetting);
+
+        if (settingsValue != null) {
+            valueList = new ArrayList<>(Arrays.asList(settingsValue.split(",")));
+        } else {
+            valueList = new ArrayList<>();
+        }
+
+        return valueList;
+    }
+
+    private static int getGlobalSettingsPkgIndex(String pkgName,
+                                                 List<String> globalSettingsDriverPkgs) {
+        for (int pkgIndex = 0; pkgIndex < globalSettingsDriverPkgs.size(); pkgIndex++) {
+            if (globalSettingsDriverPkgs.get(pkgIndex).equals(pkgName)) {
+                return pkgIndex;
+            }
+        }
+
+        return -1;
+    }
+
+    private static String getDriverForPkg(Context context, String packageName) {
+        try {
+            ContentResolver contentResolver = context.getContentResolver();
+            int allUseAngle = Settings.Global.getInt(contentResolver,
+                    Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE);
+            if (allUseAngle == 1) {
+                return sDriverMap.get(OpenGlDriverChoice.ANGLE);
+            }
+        } catch (Settings.SettingNotFoundException e) {
+            // Do nothing and move on
+        }
+
+        List<String> globalSettingsDriverPkgs =
+                getGlobalSettingsString(context,
+                        Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS);
+        List<String> globalSettingsDriverValues =
+                getGlobalSettingsString(context,
+                        Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES);
+
+        // Make sure we have a good package name
+        if ((packageName == null) || (packageName.isEmpty())) {
+            return sDriverMap.get(OpenGlDriverChoice.DEFAULT);
+        }
+        // Make sure we have good settings to use
+        if (globalSettingsDriverPkgs.isEmpty() || globalSettingsDriverValues.isEmpty()
+                || (globalSettingsDriverPkgs.size() != globalSettingsDriverValues.size())) {
+            Log.w(TAG,
+                    "Global.Settings values are invalid: "
+                        + "globalSettingsDriverPkgs.size = "
+                            + globalSettingsDriverPkgs.size() + ", "
+                        + "globalSettingsDriverValues.size = "
+                            + globalSettingsDriverValues.size());
+            return sDriverMap.get(OpenGlDriverChoice.DEFAULT);
+        }
+
+        int pkgIndex = getGlobalSettingsPkgIndex(packageName, globalSettingsDriverPkgs);
+
+        if (pkgIndex < 0) {
+            return sDriverMap.get(OpenGlDriverChoice.DEFAULT);
+        }
+
+        return globalSettingsDriverValues.get(pkgIndex);
+    }
+
     /**
      * Pass ANGLE details down to trigger enable logic
      */
-    private static void setupAngle(Context context, Bundle coreSettings) {
+    private void setupAngle(Context context, String packageName) {
+        String devOptIn = getDriverForPkg(context, packageName);
 
-        String angleEnabledApp =
-                coreSettings.getString(Settings.Global.ANGLE_ENABLED_APP);
-
-        String packageName = context.getPackageName();
-
-        boolean devOptIn = false;
-        if ((angleEnabledApp != null && packageName != null)
-                && (!angleEnabledApp.isEmpty() && !packageName.isEmpty())
-                && angleEnabledApp.equals(packageName)) {
-
-            Log.i(TAG, packageName + " opted in for ANGLE via Developer Setting");
-
-            devOptIn = true;
+        if (DEBUG) {
+            Log.v(TAG, "ANGLE Developer option for '" + packageName + "' "
+                    + "set to: '" + devOptIn + "'");
         }
 
         ApplicationInfo angleInfo;
@@ -303,8 +384,7 @@
         // Further opt-in logic is handled in native, so pass relevant info down
         // TODO: Move the ANGLE selection logic earlier so we don't need to keep these
         //       file descriptors open.
-        setAngleInfo(paths, packageName, devOptIn,
-                     rulesFd, rulesOffset, rulesLength);
+        setAngleInfo(paths, packageName, devOptIn, rulesFd, rulesOffset, rulesLength);
     }
 
     /**
@@ -452,6 +532,6 @@
     private static native void setDebugLayersGLES(String layers);
     private static native void setDriverPath(String path);
     private static native void setAngleInfo(String path, String appPackage,
-                                            boolean devOptIn, FileDescriptor rulesFd,
+                                            String devOptIn, FileDescriptor rulesFd,
                                             long rulesOffset, long rulesLength);
 }
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index abfcfaa..17ce79b 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -948,7 +948,7 @@
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
-    public static final String DISALLOW_INTELLIGENCE_CAPTURE = "no_intelligence_capture";
+    public static final String DISALLOW_CONTENT_CAPTURE = "no_content_capture";
 
     /**
      * Specifies if user switching is blocked on the current user.
@@ -1225,6 +1225,9 @@
      * system user hasn't been unlocked yet, or {@link #DISALLOW_USER_SWITCH} is set.
      * @hide
      */
+    @SystemApi
+    @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
     public boolean canSwitchUsers() {
         boolean allowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
                 mContext.getContentResolver(),
@@ -2646,6 +2649,19 @@
     }
 
     /**
+     * Removes a user and all associated data.
+     *
+     * @param user the user that needs to be removed.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    public boolean removeUser(UserHandle user) {
+        return removeUser(user.getIdentifier());
+    }
+
+
+    /**
      * Similar to {@link #removeUser(int)} except bypassing the checking of
      * {@link UserManager#DISALLOW_REMOVE_USER}
      * or {@link UserManager#DISALLOW_REMOVE_MANAGED_PROFILE}.
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index bf988ae..f114b12 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -190,4 +190,5 @@
     void abortIdleMaintenance() = 80;
     String translateAppToSystem(String path, int pid, int uid) = 81;
     String translateSystemToApp(String path, int pid, int uid) = 82;
+    void commitChanges() = 83;
 }
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index a8f3665..865b8f8 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -16,13 +16,14 @@
 
 package android.provider;
 
-
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -694,6 +695,37 @@
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/calendars");
 
         /**
+         * The content:// style URL for querying Calendars table in the work profile. Appending a
+         * calendar id using {@link ContentUris#withAppendedId(Uri, long)} will
+         * specify a single calendar.
+         *
+         * <p>The following columns are allowed to be queried via this uri:
+         * <ul>
+         * <li>{@link #_ID}</li>
+         * <li>{@link #NAME}</li>
+         * <li>{@link #CALENDAR_DISPLAY_NAME}</li>
+         * <li>{@link #CALENDAR_COLOR}</li>
+         * <li>{@link #VISIBLE}</li>
+         * <li>{@link #CALENDAR_LOCATION}</li>
+         * <li>{@link #CALENDAR_TIME_ZONE}</li>
+         * <li>{@link #IS_PRIMARY}</li>
+         * </ul>
+         *
+         * <p>{@link IllegalArgumentException} will be thrown if there exist columns in the
+         * projection of the query to this uri that are not contained in the above list.
+         *
+         * <p>This uri will return an empty cursor if the calling user is not a parent profile
+         * of a work profile, or cross profile calendar is disabled in Settings, or this uri is
+         * queried from a package that is not whitelisted by profile owner of the work profile via
+         * {@link DevicePolicyManager#addCrossProfileCalendarPackage(ComponentName, String)}.
+         *
+         * @see DevicePolicyManager#getCrossProfileCalendarPackages(ComponentName)
+         * @see Settings.Secure#CROSS_PROFILE_CALENDAR_ENABLED
+         */
+        public static final Uri ENTERPRISE_CONTENT_URI =
+                Uri.parse("content://" + AUTHORITY + "/enterprise/calendars");
+
+        /**
          * The default sort order for this table
          */
         public static final String DEFAULT_SORT_ORDER = CALENDAR_DISPLAY_NAME;
@@ -1641,6 +1673,50 @@
                 Uri.parse("content://" + AUTHORITY + "/events");
 
         /**
+         * The content:// style URL for querying Events table in the work profile. Appending an
+         * event id using {@link ContentUris#withAppendedId(Uri, long)} will
+         * specify a single event.
+         *
+         * <p>The following columns are allowed to be queried via this uri:
+         * <ul>
+         * <li>{@link #_ID}</li>
+         * <li>{@link #CALENDAR_ID}</li>
+         * <li>{@link #TITLE}</li>
+         * <li>{@link #EVENT_LOCATION}</li>
+         * <li>{@link #EVENT_COLOR}</li>
+         * <li>{@link #STATUS}</li>
+         * <li>{@link #DTSTART}</li>
+         * <li>{@link #DTEND}</li>
+         * <li>{@link #EVENT_TIMEZONE}</li>
+         * <li>{@link #EVENT_END_TIMEZONE}</li>
+         * <li>{@link #DURATION}</li>
+         * <li>{@link #ALL_DAY}</li>
+         * <li>{@link #AVAILABILITY}</li>
+         * <li>{@link #RRULE}</li>
+         * <li>{@link #RDATE}</li>
+         * <li>{@link #EXRULE}</li>
+         * <li>{@link #EXDATE}</li>
+         * <li>{@link #CALENDAR_DISPLAY_NAME}</li>
+         * <li>{@link #CALENDAR_COLOR}</li>
+         * <li>{@link #VISIBLE}</li>
+         * <li>{@link #CALENDAR_TIME_ZONE}</li>
+         * </ul>
+         *
+         * <p>{@link IllegalArgumentException} will be thrown if there exist columns in the
+         * projection of the query to this uri that are not contained in the above list.
+         *
+         * <p>This uri will return an empty cursor if the calling user is not a parent profile
+         * of a work profile, or cross profile calendar is disabled in Settings, or this uri is
+         * queried from a package that is not whitelisted by profile owner of the work profile via
+         * {@link DevicePolicyManager#addCrossProfileCalendarPackage(ComponentName, String)}.
+         *
+         * @see DevicePolicyManager#getCrossProfileCalendarPackages(ComponentName)
+         * @see Settings.Secure#CROSS_PROFILE_CALENDAR_ENABLED
+         */
+        public static final Uri ENTERPRISE_CONTENT_URI =
+                Uri.parse("content://" + AUTHORITY + "/enterprise/events");
+
+        /**
          * The content:// style URI for recurring event exceptions.  Insertions require an
          * appended event ID.  Deletion of exceptions requires both the original event ID and
          * the exception event ID (see {@link Uri.Builder#appendPath}).
@@ -1820,6 +1896,63 @@
             Uri.parse("content://" + AUTHORITY + "/instances/searchbyday");
 
         /**
+         * The content:// style URL for querying an instance range in the work profile.
+         * It supports similar semantics as {@link #CONTENT_URI}.
+         *
+         * <p>The following columns plus the columns that are whitelisted by
+         * {@link Events#ENTERPRISE_CONTENT_URI} are allowed to be queried via this uri:
+         * <ul>
+         * <li>{@link #_ID}</li>
+         * <li>{@link #EVENT_ID}</li>
+         * <li>{@link #BEGIN}</li>
+         * <li>{@link #END}</li>
+         * <li>{@link #START_DAY}</li>
+         * <li>{@link #END_DAY}</li>
+         * <li>{@link #START_MINUTE}</li>
+         * <li>{@link #END_MINUTE}</li>
+         * </ul>
+         *
+         * <p>{@link IllegalArgumentException} will be thrown if there exist columns in the
+         * projection of the query to this uri that are not contained in the above list.
+         *
+         * <p>This uri will return an empty cursor if the calling user is not a parent profile
+         * of a work profile, or cross profile calendar for the work profile is disabled in
+         * Settings, or this uri is queried from a package that is not whitelisted by
+         * profile owner of the work profile via
+         * {@link DevicePolicyManager#addCrossProfileCalendarPackage(ComponentName, String)}.
+         *
+         * @see DevicePolicyManager#getCrossProfileCalendarPackages(ComponentName)
+         * @see Settings.Secure#CROSS_PROFILE_CALENDAR_ENABLED
+         */
+        public static final Uri ENTERPRISE_CONTENT_URI =
+                Uri.parse("content://" + AUTHORITY + "/enterprise/instances/when");
+
+        /**
+         * The content:// style URL for querying an instance range by Julian
+         * Day in the work profile. It supports similar semantics as {@link #CONTENT_BY_DAY_URI}
+         * and performs similar checks as {@link #ENTERPRISE_CONTENT_URI}.
+         */
+        public static final Uri ENTERPRISE_CONTENT_BY_DAY_URI =
+                Uri.parse("content://" + AUTHORITY + "/enterprise/instances/whenbyday");
+
+        /**
+         * The content:// style URL for querying an instance range with a search
+         * term in the work profile. It supports similar semantics as {@link #CONTENT_SEARCH_URI}
+         * and performs similar checks as {@link #ENTERPRISE_CONTENT_URI}.
+         */
+        public static final Uri ENTERPRISE_CONTENT_SEARCH_URI =
+                Uri.parse("content://" + AUTHORITY + "/enterprise/instances/search");
+
+        /**
+         * The content:// style URL for querying an instance range with a search
+         * term in the work profile. It supports similar semantics as
+         * {@link #CONTENT_SEARCH_BY_DAY_URI} and performs similar checks as
+         * {@link #ENTERPRISE_CONTENT_URI}.
+         */
+        public static final Uri ENTERPRISE_CONTENT_SEARCH_BY_DAY_URI =
+                Uri.parse("content://" + AUTHORITY + "/enterprise/instances/searchbyday");
+
+        /**
          * The default sort order for this table.
          */
         private static final String DEFAULT_SORT_ORDER = "begin ASC";
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 37c84bd..ff77228 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -22,8 +22,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
-import android.content.ContentProviderClient;
+import android.content.ContentInterface;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -47,10 +48,10 @@
 import android.os.Parcelable;
 import android.os.ParcelableException;
 import android.os.RemoteException;
-import android.os.storage.StorageVolume;
-import android.util.DataUnit;
 import android.util.Log;
 
+import dalvik.system.VMRuntime;
+
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -67,8 +68,7 @@
  * All client apps must hold a valid URI permission grant to access documents,
  * typically issued when a user makes a selection through
  * {@link Intent#ACTION_OPEN_DOCUMENT}, {@link Intent#ACTION_CREATE_DOCUMENT},
- * {@link Intent#ACTION_OPEN_DOCUMENT_TREE}, or
- * {@link StorageVolume#createAccessIntent(String) StorageVolume.createAccessIntent}.
+ * or {@link Intent#ACTION_OPEN_DOCUMENT_TREE}.
  *
  * @see DocumentsProvider
  */
@@ -97,8 +97,15 @@
     @Deprecated
     public static final String EXTRA_PACKAGE_NAME = Intent.EXTRA_PACKAGE_NAME;
 
-    /** {@hide} */
-    public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
+    /**
+     * The value is decide whether to show advance mode or not.
+     * If the value is true, the local/device storage root must be
+     * visible in DocumentsUI.
+     *
+     * {@hide}
+     */
+    @SystemApi
+    public static final String EXTRA_SHOW_ADVANCED = "android.provider.extra.SHOW_ADVANCED";
 
     /** {@hide} */
     public static final String EXTRA_TARGET_URI = "android.content.extra.TARGET_URI";
@@ -111,7 +118,6 @@
      *
      * @see DocumentsProvider#querySearchDocuments(String, String[],
      *      Bundle)
-     * {@hide}
      */
     public static final String QUERY_ARG_DISPLAY_NAME = "android:query-arg-display-name";
 
@@ -124,7 +130,6 @@
      *
      * @see DocumentsProvider#querySearchDocuments(String, String[],
      *      Bundle)
-     * {@hide}
      */
     public static final String QUERY_ARG_MIME_TYPES = "android:query-arg-mime-types";
 
@@ -134,7 +139,6 @@
      *
      * @see DocumentsProvider#querySearchDocuments(String, String[],
      *      Bundle)
-     * {@hide}
      */
     public static final String QUERY_ARG_FILE_SIZE_OVER = "android:query-arg-file-size-over";
 
@@ -146,7 +150,6 @@
      * @see DocumentsProvider#querySearchDocuments(String, String[],
      *      Bundle)
      * @see Document#COLUMN_LAST_MODIFIED
-     * {@hide}
      */
     public static final String QUERY_ARG_LAST_MODIFIED_AFTER =
             "android:query-arg-last-modified-after";
@@ -158,7 +161,6 @@
      *
      * @see DocumentsProvider#querySearchDocuments(String, String[],
      *      Bundle)
-     * {@hide}
      */
     public static final String QUERY_ARG_EXCLUDE_MEDIA = "android:query-arg-exclude-media";
 
@@ -216,18 +218,21 @@
     public static final String
             ACTION_DOCUMENT_SETTINGS = "android.provider.action.DOCUMENT_SETTINGS";
 
-    /** {@hide} */
+    /**
+     * The action to manage document in Downloads root in DocumentsUI.
+     *  {@hide}
+     */
+    @SystemApi
     public static final String ACTION_MANAGE_DOCUMENT = "android.provider.action.MANAGE_DOCUMENT";
 
-    /** {@hide} */
+    /**
+     * The action to launch the settings of this root.
+     * {@hide}
+     */
+    @SystemApi
     public static final String
             ACTION_DOCUMENT_ROOT_SETTINGS = "android.provider.action.DOCUMENT_ROOT_SETTINGS";
 
-    /**
-     * Buffer is large enough to rewind past any EXIF headers.
-     */
-    private static final int THUMBNAIL_BUFFER_SIZE = (int) DataUnit.KIBIBYTES.toBytes(128);
-
     /** {@hide} */
     public static final String EXTERNAL_STORAGE_PROVIDER_AUTHORITY =
             "com.android.externalstorage.documents";
@@ -235,10 +240,19 @@
     /** {@hide} */
     public static final String PACKAGE_DOCUMENTS_UI = "com.android.documentsui";
 
-    /** {@hide} */
-    public static final String METADATA_TYPES = "android:documentMetadataType";
+    /**
+     * Get string array identifies the type or types of metadata returned
+     * using DocumentsContract#getDocumentMetadata.
+     *
+     * @see #getDocumentMetadata(ContentResolver, Uri)
+     */
+    public static final String METADATA_TYPES = "android:documentMetadataTypes";
 
-    /** {@hide} */
+    /**
+     * Get Exif information using DocumentsContract#getDocumentMetadata.
+     *
+     * @see #getDocumentMetadata(ContentResolver, Uri)
+     */
     public static final String METADATA_EXIF = "android:documentExif";
 
     /**
@@ -361,7 +375,7 @@
          * Flag indicating that a document can be represented as a thumbnail.
          *
          * @see #COLUMN_FLAGS
-         * @see DocumentsContract#getDocumentThumbnail(ContentResolver, Uri,
+         * @see DocumentsContract#getDocumentThumbnail(ContentInterface, Uri,
          *      Point, CancellationSignal)
          * @see DocumentsProvider#openDocumentThumbnail(String, Point,
          *      android.os.CancellationSignal)
@@ -387,7 +401,7 @@
          * Flag indicating that a document is deletable.
          *
          * @see #COLUMN_FLAGS
-         * @see DocumentsContract#deleteDocument(ContentResolver, Uri)
+         * @see DocumentsContract#deleteDocument(ContentInterface, Uri)
          * @see DocumentsProvider#deleteDocument(String)
          */
         public static final int FLAG_SUPPORTS_DELETE = 1 << 2;
@@ -425,8 +439,7 @@
          * Flag indicating that a document can be renamed.
          *
          * @see #COLUMN_FLAGS
-         * @see DocumentsContract#renameDocument(ContentResolver, Uri,
-         *      String)
+         * @see DocumentsContract#renameDocument(ContentInterface, Uri, String)
          * @see DocumentsProvider#renameDocument(String, String)
          */
         public static final int FLAG_SUPPORTS_RENAME = 1 << 6;
@@ -436,7 +449,7 @@
          * within the same document provider.
          *
          * @see #COLUMN_FLAGS
-         * @see DocumentsContract#copyDocument(ContentResolver, Uri, Uri)
+         * @see DocumentsContract#copyDocument(ContentInterface, Uri, Uri)
          * @see DocumentsProvider#copyDocument(String, String)
          */
         public static final int FLAG_SUPPORTS_COPY = 1 << 7;
@@ -446,7 +459,7 @@
          * within the same document provider.
          *
          * @see #COLUMN_FLAGS
-         * @see DocumentsContract#moveDocument(ContentResolver, Uri, Uri, Uri)
+         * @see DocumentsContract#moveDocument(ContentInterface, Uri, Uri, Uri)
          * @see DocumentsProvider#moveDocument(String, String, String)
          */
         public static final int FLAG_SUPPORTS_MOVE = 1 << 8;
@@ -470,7 +483,7 @@
          * Flag indicating that a document can be removed from a parent.
          *
          * @see #COLUMN_FLAGS
-         * @see DocumentsContract#removeDocument(ContentResolver, Uri, Uri)
+         * @see DocumentsContract#removeDocument(ContentInterface, Uri, Uri)
          * @see DocumentsProvider#removeDocument(String, String)
          */
         public static final int FLAG_SUPPORTS_REMOVE = 1 << 10;
@@ -498,16 +511,17 @@
          * if they represent a failed download.
          *
          * @see #COLUMN_FLAGS
-         * @hide
          */
-        public static final int FLAG_PARTIAL = 1 << 16;
+        public static final int FLAG_PARTIAL = 1 << 13;
 
         /**
          * Flag indicating that a document has available metadata that can be read
          * using DocumentsContract#getDocumentMetadata
-         * @hide
+         *
+         * @see #COLUMN_FLAGS
+         * @see DocumentsContract#getDocumentMetadata(ContentResolver, Uri)
          */
-        public static final int FLAG_SUPPORTS_METADATA = 1 << 17;
+        public static final int FLAG_SUPPORTS_METADATA = 1 << 14;
     }
 
     /**
@@ -663,7 +677,7 @@
          * Flag indicating that this root can be ejected.
          *
          * @see #COLUMN_FLAGS
-         * @see DocumentsContract#ejectRoot(ContentResolver, Uri)
+         * @see DocumentsContract#ejectRoot(ContentInterface, Uri)
          * @see DocumentsProvider#ejectRoot(String)
          */
         public static final int FLAG_SUPPORTS_EJECT = 1 << 5;
@@ -679,44 +693,46 @@
          * @see #COLUMN_FLAGS
          * @see ContentResolver#notifyChange(Uri,
          *      android.database.ContentObserver, boolean)
-         * @hide
          */
-        public static final int FLAG_EMPTY = 1 << 16;
+        public static final int FLAG_EMPTY = 1 << 6;
 
         /**
          * Flag indicating that this root should only be visible to advanced
          * users.
          *
          * @see #COLUMN_FLAGS
-         * @hide
+         * {@hide}
          */
-        @UnsupportedAppUsage
-        public static final int FLAG_ADVANCED = 1 << 17;
+        @SystemApi
+        public static final int FLAG_ADVANCED = 1 << 16;
 
         /**
          * Flag indicating that this root has settings.
          *
          * @see #COLUMN_FLAGS
          * @see DocumentsContract#ACTION_DOCUMENT_ROOT_SETTINGS
-         * @hide
+         * {@hide}
          */
-        public static final int FLAG_HAS_SETTINGS = 1 << 18;
+        @SystemApi
+        public static final int FLAG_HAS_SETTINGS = 1 << 17;
 
         /**
          * Flag indicating that this root is on removable SD card storage.
          *
          * @see #COLUMN_FLAGS
-         * @hide
+         * {@hide}
          */
-        public static final int FLAG_REMOVABLE_SD = 1 << 19;
+        @SystemApi
+        public static final int FLAG_REMOVABLE_SD = 1 << 18;
 
         /**
          * Flag indicating that this root is on removable USB storage.
          *
          * @see #COLUMN_FLAGS
-         * @hide
+         * {@hide}
          */
-        public static final int FLAG_REMOVABLE_USB = 1 << 20;
+        @SystemApi
+        public static final int FLAG_REMOVABLE_USB = 1 << 19;
     }
 
     /**
@@ -784,10 +800,7 @@
     /** {@hide} */
     public static final String EXTRA_URI_PERMISSIONS = "uriPermissions";
 
-    /**
-     * @see #createWebLinkIntent(ContentResolver, Uri, Bundle)
-     * {@hide}
-     */
+    /** {@hide} */
     public static final String EXTRA_OPTIONS = "options";
 
     private static final String PATH_ROOT = "root";
@@ -1090,8 +1103,6 @@
      * Test if the given URI represents roots backed by {@link DocumentsProvider}.
      *
      * @see #buildRootsUri(String)
-     *
-     * {@hide}
      */
     public static boolean isRootsUri(Context context, @Nullable Uri uri) {
         return isRootUri(context, uri, 1 /* pathSize */);
@@ -1101,8 +1112,6 @@
      * Test if the given URI represents specific root backed by {@link DocumentsProvider}.
      *
      * @see #buildRootUri(String, String)
-     *
-     * {@hide}
      */
     public static boolean isRootUri(Context context, @Nullable Uri uri) {
         return isRootUri(context, uri, 2 /* pathSize */);
@@ -1200,13 +1209,23 @@
         return bundle.getString(QUERY_ARG_DISPLAY_NAME, "" /* defaultValue */);
     }
 
-    /** {@hide} */
-    @UnsupportedAppUsage
+    /**
+     * Build URI that append the query parameter {@link PARAM_MANAGE} to
+     * enable the manage mode.
+     * @see DocumentsProvider#queryChildDocumentsForManage(String parentDocId, String[], String)
+     * {@hide}
+     */
+    @SystemApi
     public static Uri setManageMode(Uri uri) {
         return uri.buildUpon().appendQueryParameter(PARAM_MANAGE, "true").build();
     }
 
-    /** {@hide} */
+    /**
+     * Extract the manage mode from a URI built by
+     * {@link #setManageMode(Uri)}.
+     * {@hide}
+     */
+    @SystemApi
     public static boolean isManageMode(Uri uri) {
         return uri.getBooleanQueryParameter(PARAM_MANAGE, false);
     }
@@ -1226,32 +1245,20 @@
      * @see DocumentsProvider#openDocumentThumbnail(String, Point,
      *      android.os.CancellationSignal)
      */
-    public static Bitmap getDocumentThumbnail(
-            ContentResolver resolver, Uri documentUri, Point size, CancellationSignal signal)
-            throws FileNotFoundException {
-        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
-                documentUri.getAuthority());
+    public static Bitmap getDocumentThumbnail(ContentInterface content, Uri documentUri, Point size,
+            CancellationSignal signal) throws FileNotFoundException {
         try {
-            return getDocumentThumbnail(client, documentUri, size, signal);
+            return ContentResolver.loadThumbnail(content, documentUri, Point.convert(size), signal,
+                    ImageDecoder.ALLOCATOR_SOFTWARE);
         } catch (Exception e) {
             if (!(e instanceof OperationCanceledException)) {
                 Log.w(TAG, "Failed to load thumbnail for " + documentUri + ": " + e);
             }
-            rethrowIfNecessary(resolver, e);
+            rethrowIfNecessary(e);
             return null;
-        } finally {
-            ContentProviderClient.releaseQuietly(client);
         }
     }
 
-    /** {@hide} */
-    @UnsupportedAppUsage
-    public static Bitmap getDocumentThumbnail(ContentProviderClient client, Uri documentUri,
-            Point size, CancellationSignal signal) throws IOException {
-        return ContentResolver.loadThumbnail(client, documentUri, Point.convert(size), signal,
-                ImageDecoder.ALLOCATOR_SOFTWARE);
-    }
-
     /**
      * Create a new document with given MIME type and display name.
      *
@@ -1260,49 +1267,55 @@
      * @param displayName name of new document
      * @return newly created document, or {@code null} if failed
      */
-    public static Uri createDocument(ContentResolver resolver, Uri parentDocumentUri,
+    public static Uri createDocument(ContentInterface content, Uri parentDocumentUri,
             String mimeType, String displayName) throws FileNotFoundException {
-        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
-                parentDocumentUri.getAuthority());
         try {
-            return createDocument(client, parentDocumentUri, mimeType, displayName);
+            final Bundle in = new Bundle();
+            in.putParcelable(DocumentsContract.EXTRA_URI, parentDocumentUri);
+            in.putString(Document.COLUMN_MIME_TYPE, mimeType);
+            in.putString(Document.COLUMN_DISPLAY_NAME, displayName);
+
+            final Bundle out = content.call(parentDocumentUri.getAuthority(),
+                    METHOD_CREATE_DOCUMENT, null, in);
+            return out.getParcelable(DocumentsContract.EXTRA_URI);
         } catch (Exception e) {
             Log.w(TAG, "Failed to create document", e);
-            rethrowIfNecessary(resolver, e);
+            rethrowIfNecessary(e);
             return null;
-        } finally {
-            ContentProviderClient.releaseQuietly(client);
         }
     }
 
-    /** {@hide} */
-    public static Uri createDocument(ContentProviderClient client, Uri parentDocumentUri,
-            String mimeType, String displayName) throws RemoteException {
-        final Bundle in = new Bundle();
-        in.putParcelable(DocumentsContract.EXTRA_URI, parentDocumentUri);
-        in.putString(Document.COLUMN_MIME_TYPE, mimeType);
-        in.putString(Document.COLUMN_DISPLAY_NAME, displayName);
 
-        final Bundle out = client.call(METHOD_CREATE_DOCUMENT, null, in);
-        return out.getParcelable(DocumentsContract.EXTRA_URI);
-    }
+    /**
+     * Test if a document is descendant (child, grandchild, etc) from the given
+     * parent.
+     *
+     * @param parentDocumentUri parent to verify against.
+     * @param childDocumentUri child to verify.
+     * @return if given document is a descendant of the given parent.
+     * @see Root#FLAG_SUPPORTS_IS_CHILD
+     */
+    public static boolean isChildDocument(ContentInterface content, Uri parentDocumentUri,
+            Uri childDocumentUri) throws FileNotFoundException {
+        try {
+            final Bundle in = new Bundle();
+            in.putParcelable(DocumentsContract.EXTRA_URI, parentDocumentUri);
+            in.putParcelable(DocumentsContract.EXTRA_TARGET_URI, childDocumentUri);
 
-    /** {@hide} */
-    public static boolean isChildDocument(ContentProviderClient client, Uri parentDocumentUri,
-            Uri childDocumentUri) throws RemoteException {
-
-        final Bundle in = new Bundle();
-        in.putParcelable(DocumentsContract.EXTRA_URI, parentDocumentUri);
-        in.putParcelable(DocumentsContract.EXTRA_TARGET_URI, childDocumentUri);
-
-        final Bundle out = client.call(METHOD_IS_CHILD_DOCUMENT, null, in);
-        if (out == null) {
-            throw new RemoteException("Failed to get a reponse from isChildDocument query.");
+            final Bundle out = content.call(parentDocumentUri.getAuthority(),
+                    METHOD_IS_CHILD_DOCUMENT, null, in);
+            if (out == null) {
+                throw new RemoteException("Failed to get a reponse from isChildDocument query.");
+            }
+            if (!out.containsKey(DocumentsContract.EXTRA_RESULT)) {
+                throw new RemoteException("Response did not include result field..");
+            }
+            return out.getBoolean(DocumentsContract.EXTRA_RESULT);
+        } catch (Exception e) {
+            Log.w(TAG, "Failed to create document", e);
+            rethrowIfNecessary(e);
+            return false;
         }
-        if (!out.containsKey(DocumentsContract.EXTRA_RESULT)) {
-            throw new RemoteException("Response did not include result field..");
-        }
-        return out.getBoolean(DocumentsContract.EXTRA_RESULT);
     }
 
     /**
@@ -1318,64 +1331,46 @@
      * @return the existing or new document after the rename, or {@code null} if
      *         failed.
      */
-    public static Uri renameDocument(ContentResolver resolver, Uri documentUri,
+    public static Uri renameDocument(ContentInterface content, Uri documentUri,
             String displayName) throws FileNotFoundException {
-        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
-                documentUri.getAuthority());
         try {
-            return renameDocument(client, documentUri, displayName);
+            final Bundle in = new Bundle();
+            in.putParcelable(DocumentsContract.EXTRA_URI, documentUri);
+            in.putString(Document.COLUMN_DISPLAY_NAME, displayName);
+
+            final Bundle out = content.call(documentUri.getAuthority(),
+                    METHOD_RENAME_DOCUMENT, null, in);
+            final Uri outUri = out.getParcelable(DocumentsContract.EXTRA_URI);
+            return (outUri != null) ? outUri : documentUri;
         } catch (Exception e) {
             Log.w(TAG, "Failed to rename document", e);
-            rethrowIfNecessary(resolver, e);
+            rethrowIfNecessary(e);
             return null;
-        } finally {
-            ContentProviderClient.releaseQuietly(client);
         }
     }
 
-    /** {@hide} */
-    public static Uri renameDocument(ContentProviderClient client, Uri documentUri,
-            String displayName) throws RemoteException {
-        final Bundle in = new Bundle();
-        in.putParcelable(DocumentsContract.EXTRA_URI, documentUri);
-        in.putString(Document.COLUMN_DISPLAY_NAME, displayName);
-
-        final Bundle out = client.call(METHOD_RENAME_DOCUMENT, null, in);
-        final Uri outUri = out.getParcelable(DocumentsContract.EXTRA_URI);
-        return (outUri != null) ? outUri : documentUri;
-    }
-
     /**
      * Delete the given document.
      *
      * @param documentUri document with {@link Document#FLAG_SUPPORTS_DELETE}
      * @return if the document was deleted successfully.
      */
-    public static boolean deleteDocument(ContentResolver resolver, Uri documentUri)
+    public static boolean deleteDocument(ContentInterface content, Uri documentUri)
             throws FileNotFoundException {
-        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
-                documentUri.getAuthority());
         try {
-            deleteDocument(client, documentUri);
+            final Bundle in = new Bundle();
+            in.putParcelable(DocumentsContract.EXTRA_URI, documentUri);
+
+            content.call(documentUri.getAuthority(),
+                    METHOD_DELETE_DOCUMENT, null, in);
             return true;
         } catch (Exception e) {
             Log.w(TAG, "Failed to delete document", e);
-            rethrowIfNecessary(resolver, e);
+            rethrowIfNecessary(e);
             return false;
-        } finally {
-            ContentProviderClient.releaseQuietly(client);
         }
     }
 
-    /** {@hide} */
-    public static void deleteDocument(ContentProviderClient client, Uri documentUri)
-            throws RemoteException {
-        final Bundle in = new Bundle();
-        in.putParcelable(DocumentsContract.EXTRA_URI, documentUri);
-
-        client.call(METHOD_DELETE_DOCUMENT, null, in);
-    }
-
     /**
      * Copies the given document.
      *
@@ -1384,32 +1379,23 @@
      *         document's copy.
      * @return the copied document, or {@code null} if failed.
      */
-    public static Uri copyDocument(ContentResolver resolver, Uri sourceDocumentUri,
+    public static Uri copyDocument(ContentInterface content, Uri sourceDocumentUri,
             Uri targetParentDocumentUri) throws FileNotFoundException {
-        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
-                sourceDocumentUri.getAuthority());
         try {
-            return copyDocument(client, sourceDocumentUri, targetParentDocumentUri);
+            final Bundle in = new Bundle();
+            in.putParcelable(DocumentsContract.EXTRA_URI, sourceDocumentUri);
+            in.putParcelable(DocumentsContract.EXTRA_TARGET_URI, targetParentDocumentUri);
+
+            final Bundle out = content.call(sourceDocumentUri.getAuthority(),
+                    METHOD_COPY_DOCUMENT, null, in);
+            return out.getParcelable(DocumentsContract.EXTRA_URI);
         } catch (Exception e) {
             Log.w(TAG, "Failed to copy document", e);
-            rethrowIfNecessary(resolver, e);
+            rethrowIfNecessary(e);
             return null;
-        } finally {
-            ContentProviderClient.releaseQuietly(client);
         }
     }
 
-    /** {@hide} */
-    public static Uri copyDocument(ContentProviderClient client, Uri sourceDocumentUri,
-            Uri targetParentDocumentUri) throws RemoteException {
-        final Bundle in = new Bundle();
-        in.putParcelable(DocumentsContract.EXTRA_URI, sourceDocumentUri);
-        in.putParcelable(DocumentsContract.EXTRA_TARGET_URI, targetParentDocumentUri);
-
-        final Bundle out = client.call(METHOD_COPY_DOCUMENT, null, in);
-        return out.getParcelable(DocumentsContract.EXTRA_URI);
-    }
-
     /**
      * Moves the given document under a new parent.
      *
@@ -1419,35 +1405,24 @@
      *         document.
      * @return the moved document, or {@code null} if failed.
      */
-    public static Uri moveDocument(ContentResolver resolver, Uri sourceDocumentUri,
+    public static Uri moveDocument(ContentInterface content, Uri sourceDocumentUri,
             Uri sourceParentDocumentUri, Uri targetParentDocumentUri) throws FileNotFoundException {
-        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
-                sourceDocumentUri.getAuthority());
         try {
-            return moveDocument(client, sourceDocumentUri, sourceParentDocumentUri,
-                    targetParentDocumentUri);
+            final Bundle in = new Bundle();
+            in.putParcelable(DocumentsContract.EXTRA_URI, sourceDocumentUri);
+            in.putParcelable(DocumentsContract.EXTRA_PARENT_URI, sourceParentDocumentUri);
+            in.putParcelable(DocumentsContract.EXTRA_TARGET_URI, targetParentDocumentUri);
+
+            final Bundle out = content.call(sourceDocumentUri.getAuthority(),
+                    METHOD_MOVE_DOCUMENT, null, in);
+            return out.getParcelable(DocumentsContract.EXTRA_URI);
         } catch (Exception e) {
             Log.w(TAG, "Failed to move document", e);
-            rethrowIfNecessary(resolver, e);
+            rethrowIfNecessary(e);
             return null;
-        } finally {
-            ContentProviderClient.releaseQuietly(client);
         }
     }
 
-    /** {@hide} */
-    @UnsupportedAppUsage
-    public static Uri moveDocument(ContentProviderClient client, Uri sourceDocumentUri,
-            Uri sourceParentDocumentUri, Uri targetParentDocumentUri) throws RemoteException {
-        final Bundle in = new Bundle();
-        in.putParcelable(DocumentsContract.EXTRA_URI, sourceDocumentUri);
-        in.putParcelable(DocumentsContract.EXTRA_PARENT_URI, sourceParentDocumentUri);
-        in.putParcelable(DocumentsContract.EXTRA_TARGET_URI, targetParentDocumentUri);
-
-        final Bundle out = client.call(METHOD_MOVE_DOCUMENT, null, in);
-        return out.getParcelable(DocumentsContract.EXTRA_URI);
-    }
-
     /**
      * Removes the given document from a parent directory.
      *
@@ -1458,68 +1433,50 @@
      * @param parentDocumentUri parent document of the document to remove.
      * @return true if the document was removed successfully.
      */
-    public static boolean removeDocument(ContentResolver resolver, Uri documentUri,
+    public static boolean removeDocument(ContentInterface content, Uri documentUri,
             Uri parentDocumentUri) throws FileNotFoundException {
-        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
-                documentUri.getAuthority());
         try {
-            removeDocument(client, documentUri, parentDocumentUri);
+            final Bundle in = new Bundle();
+            in.putParcelable(DocumentsContract.EXTRA_URI, documentUri);
+            in.putParcelable(DocumentsContract.EXTRA_PARENT_URI, parentDocumentUri);
+
+            content.call(documentUri.getAuthority(),
+                    METHOD_REMOVE_DOCUMENT, null, in);
             return true;
         } catch (Exception e) {
             Log.w(TAG, "Failed to remove document", e);
-            rethrowIfNecessary(resolver, e);
+            rethrowIfNecessary(e);
             return false;
-        } finally {
-            ContentProviderClient.releaseQuietly(client);
         }
     }
 
-    /** {@hide} */
-    public static void removeDocument(ContentProviderClient client, Uri documentUri,
-            Uri parentDocumentUri) throws RemoteException {
-        final Bundle in = new Bundle();
-        in.putParcelable(DocumentsContract.EXTRA_URI, documentUri);
-        in.putParcelable(DocumentsContract.EXTRA_PARENT_URI, parentDocumentUri);
-
-        client.call(METHOD_REMOVE_DOCUMENT, null, in);
-    }
-
     /**
      * Ejects the given root. It throws {@link IllegalStateException} when ejection failed.
      *
      * @param rootUri root with {@link Root#FLAG_SUPPORTS_EJECT} to be ejected
      */
-    public static void ejectRoot(ContentResolver resolver, Uri rootUri) {
-        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
-                rootUri.getAuthority());
+    public static void ejectRoot(ContentInterface content, Uri rootUri) {
         try {
-            ejectRoot(client, rootUri);
+            final Bundle in = new Bundle();
+            in.putParcelable(DocumentsContract.EXTRA_URI, rootUri);
+
+            content.call(rootUri.getAuthority(),
+                    METHOD_EJECT_ROOT, null, in);
         } catch (RemoteException e) {
             e.rethrowAsRuntimeException();
-        } finally {
-            ContentProviderClient.releaseQuietly(client);
         }
     }
 
-    /** {@hide} */
-    public static void ejectRoot(ContentProviderClient client, Uri rootUri)
-            throws RemoteException {
-        final Bundle in = new Bundle();
-        in.putParcelable(DocumentsContract.EXTRA_URI, rootUri);
-
-        client.call(METHOD_EJECT_ROOT, null, in);
-    }
-
     /**
      * Returns metadata associated with the document. The type of metadata returned
      * is specific to the document type. For example the data returned for an image
-     * file will likely consist primarily or soley of EXIF metadata.
+     * file will likely consist primarily or solely of EXIF metadata.
      *
      * <p>The returned {@link Bundle} will contain zero or more entries depending
      * on the type of data supported by the document provider.
      *
      * <ol>
-     * <li>A {@link DocumentsContract.METADATA_TYPES} containing a {@code String[]} value.
+     * <li>A {@link DocumentsContract#METADATA_TYPES} containing a {@code String[]} value.
      *     The string array identifies the type or types of metadata returned. Each
      *     value in the can be used to access a {@link Bundle} of data
      *     containing that type of data.
@@ -1539,69 +1496,23 @@
      *
      * @param documentUri a Document URI
      * @return a Bundle of Bundles.
-     * {@hide}
      */
-    public static Bundle getDocumentMetadata(ContentResolver resolver, Uri documentUri)
+    public static Bundle getDocumentMetadata(ContentInterface content, Uri documentUri)
             throws FileNotFoundException {
-        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
-                documentUri.getAuthority());
-
         try {
-            return getDocumentMetadata(client, documentUri);
+            final Bundle in = new Bundle();
+            in.putParcelable(EXTRA_URI, documentUri);
+
+            return content.call(documentUri.getAuthority(),
+                    METHOD_GET_DOCUMENT_METADATA, null, in);
         } catch (Exception e) {
             Log.w(TAG, "Failed to get document metadata");
-            rethrowIfNecessary(resolver, e);
+            rethrowIfNecessary(e);
             return null;
-        } finally {
-            ContentProviderClient.releaseQuietly(client);
         }
     }
 
     /**
-     * Returns metadata associated with the document. The type of metadata returned
-     * is specific to the document type. For example the data returned for an image
-     * file will likely consist primarily or soley of EXIF metadata.
-     *
-     * <p>The returned {@link Bundle} will contain zero or more entries depending
-     * on the type of data supported by the document provider.
-     *
-     * <ol>
-     * <li>A {@link DocumentsContract.METADATA_TYPES} containing a {@code String[]} value.
-     *     The string array identifies the type or types of metadata returned. Each
-     *     value in the can be used to access a {@link Bundle} of data
-     *     containing that type of data.
-     * <li>An entry each for each type of returned metadata. Each set of metadata is
-     *     itself represented as a bundle and accessible via a string key naming
-     *     the type of data.
-     * </ol>
-     *
-     * <p>Example:
-     * <p><pre><code>
-     *     Bundle metadata = DocumentsContract.getDocumentMetadata(client, imageDocUri, tags);
-     *     if (metadata.containsKey(DocumentsContract.METADATA_EXIF)) {
-     *         Bundle exif = metadata.getBundle(DocumentsContract.METADATA_EXIF);
-     *         int imageLength = exif.getInt(ExifInterface.TAG_IMAGE_LENGTH);
-     *     }
-     * </code></pre>
-     *
-     * @param documentUri a Document URI
-     * @return a Bundle of Bundles.
-     * {@hide}
-     */
-    public static Bundle getDocumentMetadata(
-            ContentProviderClient client, Uri documentUri) throws RemoteException {
-        final Bundle in = new Bundle();
-        in.putParcelable(EXTRA_URI, documentUri);
-
-        final Bundle out = client.call(METHOD_GET_DOCUMENT_METADATA, null, in);
-
-        if (out == null) {
-            throw new RemoteException("Failed to get a response from getDocumentMetadata");
-        }
-        return out;
-    }
-
-    /**
      * Finds the canonical path from the top of the document tree.
      *
      * The {@link Path#getPath()} of the return value contains the document ID
@@ -1614,52 +1525,25 @@
      * @return the path of the document, or {@code null} if failed.
      * @see DocumentsProvider#findDocumentPath(String, String)
      */
-    public static Path findDocumentPath(ContentResolver resolver, Uri treeUri)
+    public static Path findDocumentPath(ContentInterface content, Uri treeUri)
             throws FileNotFoundException {
         checkArgument(isTreeUri(treeUri), treeUri + " is not a tree uri.");
 
-        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
-                treeUri.getAuthority());
         try {
-            return findDocumentPath(client, treeUri);
+            final Bundle in = new Bundle();
+            in.putParcelable(DocumentsContract.EXTRA_URI, treeUri);
+
+            final Bundle out = content.call(treeUri.getAuthority(),
+                    METHOD_FIND_DOCUMENT_PATH, null, in);
+            return out.getParcelable(DocumentsContract.EXTRA_RESULT);
         } catch (Exception e) {
             Log.w(TAG, "Failed to find path", e);
-            rethrowIfNecessary(resolver, e);
+            rethrowIfNecessary(e);
             return null;
-        } finally {
-            ContentProviderClient.releaseQuietly(client);
         }
     }
 
     /**
-     * Finds the canonical path. If uri is a document uri returns path from a root and
-     * its associated root id. If uri is a tree uri returns the path from the top of
-     * the tree. The {@link Path#getPath()} of the return value contains document ID
-     * starts from the top of the tree or the root document to the requested document,
-     * both inclusive.
-     *
-     * Callers can expect the root ID returned from multiple calls to this method is
-     * consistent.
-     *
-     * @param uri uri of the document which path is requested. It can be either a
-     *          plain document uri or a tree uri.
-     * @return the path of the document.
-     * @see DocumentsProvider#findDocumentPath(String, String)
-     *
-     * {@hide}
-     */
-    public static Path findDocumentPath(ContentProviderClient client, Uri uri)
-            throws RemoteException {
-
-        final Bundle in = new Bundle();
-        in.putParcelable(DocumentsContract.EXTRA_URI, uri);
-
-        final Bundle out = client.call(METHOD_FIND_DOCUMENT_PATH, null, in);
-
-        return out.getParcelable(DocumentsContract.EXTRA_RESULT);
-    }
-
-    /**
      * Creates an intent for obtaining a web link for the specified document.
      *
      * <p>Note, that due to internal limitations, if there is already a web link
@@ -1710,40 +1594,29 @@
      * @see DocumentsProvider#createWebLinkIntent(String, Bundle)
      * @see Intent#EXTRA_EMAIL
      */
-    public static IntentSender createWebLinkIntent(ContentResolver resolver, Uri uri,
+    public static IntentSender createWebLinkIntent(ContentInterface content, Uri uri,
             Bundle options) throws FileNotFoundException {
-        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
-                uri.getAuthority());
         try {
-            return createWebLinkIntent(client, uri, options);
+            final Bundle in = new Bundle();
+            in.putParcelable(DocumentsContract.EXTRA_URI, uri);
+
+            // Options may be provider specific, so put them in a separate bundle to
+            // avoid overriding the Uri.
+            if (options != null) {
+                in.putBundle(EXTRA_OPTIONS, options);
+            }
+
+            final Bundle out = content.call(uri.getAuthority(),
+                    METHOD_CREATE_WEB_LINK_INTENT, null, in);
+            return out.getParcelable(DocumentsContract.EXTRA_RESULT);
         } catch (Exception e) {
             Log.w(TAG, "Failed to create a web link intent", e);
-            rethrowIfNecessary(resolver, e);
+            rethrowIfNecessary(e);
             return null;
-        } finally {
-            ContentProviderClient.releaseQuietly(client);
         }
     }
 
     /**
-     * {@hide}
-     */
-    public static IntentSender createWebLinkIntent(ContentProviderClient client, Uri uri,
-            Bundle options) throws RemoteException {
-        final Bundle in = new Bundle();
-        in.putParcelable(DocumentsContract.EXTRA_URI, uri);
-
-        // Options may be provider specific, so put them in a separate bundle to
-        // avoid overriding the Uri.
-        if (options != null) {
-            in.putBundle(EXTRA_OPTIONS, options);
-        }
-
-        final Bundle out = client.call(METHOD_CREATE_WEB_LINK_INTENT, null, in);
-        return out.getParcelable(DocumentsContract.EXTRA_RESULT);
-    }
-
-    /**
      * Open the given image for thumbnail purposes, using any embedded EXIF
      * thumbnail if available, and providing orientation hints from the parent
      * image.
@@ -1783,10 +1656,9 @@
         return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH, extras);
     }
 
-    private static void rethrowIfNecessary(ContentResolver resolver, Exception e)
-            throws FileNotFoundException {
+    private static void rethrowIfNecessary(Exception e) throws FileNotFoundException {
         // We only want to throw applications targetting O and above
-        if (resolver.getTargetSdkVersion() >= Build.VERSION_CODES.O) {
+        if (VMRuntime.getRuntime().getTargetSdkVersion() >= Build.VERSION_CODES.O) {
             if (e instanceof ParcelableException) {
                 ((ParcelableException) e).maybeRethrow(FileNotFoundException.class);
             } else if (e instanceof RemoteException) {
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 6ab72c7..70c84f8 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -691,7 +691,6 @@
      * @see DocumentsContract#EXTRA_LOADING
      * @see DocumentsContract#EXTRA_INFO
      * @see DocumentsContract#EXTRA_ERROR
-     * {@hide}
      */
     @SuppressWarnings("unused")
     public Cursor querySearchDocuments(String rootId, String[] projection, Bundle queryArgs)
@@ -711,7 +710,28 @@
         throw new UnsupportedOperationException("Eject not supported");
     }
 
-    /** {@hide} */
+    /**
+     * Returns metadata associated with the document. The type of metadata returned
+     * is specific to the document type. For example the data returned for an image
+     * file will likely consist primarily or solely of EXIF metadata.
+     *
+     * <p>The returned {@link Bundle} will contain zero or more entries depending
+     * on the type of data supported by the document provider.
+     *
+     * <ol>
+     * <li>A {@link DocumentsContract#METADATA_TYPES} containing a {@code String[]} value.
+     *     The string array identifies the type or types of metadata returned. Each
+     *     value in the can be used to access a {@link Bundle} of data
+     *     containing that type of data.
+     * <li>An entry each for each type of returned metadata. Each set of metadata is
+     *     itself represented as a bundle and accessible via a string key naming
+     *     the type of data.
+     * </ol>
+     *
+     * @param documentId get the metadata of the document
+     * @return a Bundle of Bundles.
+     * @see DocumentsContract#getDocumentMetadata(ContentResolver, Uri)
+     */
     public @Nullable Bundle getDocumentMetadata(String documentId)
             throws FileNotFoundException {
         throw new UnsupportedOperationException("Metadata not supported");
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 0299e41..1451165 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -16,11 +16,15 @@
 
 package android.provider;
 
+import android.annotation.BytesLong;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.AppGlobals;
@@ -102,6 +106,11 @@
     /** {@hide} */
     public static final String GET_MEDIA_URI_CALL = "get_media_uri";
 
+    /** {@hide} */
+    public static final String GET_CONTRIBUTED_MEDIA_CALL = "get_contributed_media";
+    /** {@hide} */
+    public static final String DELETE_CONTRIBUTED_MEDIA_CALL = "delete_contributed_media";
+
     /**
      * This is for internal use by the media scanner only.
      * Name of the (optional) Uri parameter that determines whether to skip deleting
@@ -2865,4 +2874,47 @@
             throw e.rethrowAsRuntimeException();
         }
     }
+
+    /**
+     * Calculate size of media contributed by given package under the calling
+     * user. The meaning of "contributed" means it won't automatically be
+     * deleted when the app is uninstalled.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA)
+    public static @BytesLong long getContributedMediaSize(Context context, String packageName) {
+        try (ContentProviderClient client = context.getContentResolver()
+                .acquireContentProviderClient(AUTHORITY)) {
+            final Bundle in = new Bundle();
+            in.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
+            final Bundle out = client.call(GET_CONTRIBUTED_MEDIA_CALL, null, in);
+            return out.getLong(Intent.EXTRA_INDEX);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Delete all media contributed by given package under the calling user. The
+     * meaning of "contributed" means it won't automatically be deleted when the
+     * app is uninstalled.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA)
+    public static void deleteContributedMedia(Context context, String packageName) {
+        try (ContentProviderClient client = context.getContentResolver()
+                .acquireContentProviderClient(AUTHORITY)) {
+            final Bundle in = new Bundle();
+            in.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
+            client.call(DELETE_CONTRIBUTED_MEDIA_CALL, null, in);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c3217a2..de6afcb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1680,6 +1680,11 @@
      */
     public static final String CALL_METHOD_TAG_KEY = "_tag";
 
+    /**
+     * @hide - String argument extra to the fast-path call()-based requests
+     */
+    public static final String CALL_METHOD_PREFIX_KEY = "_prefix";
+
     /** @hide - Private call() method to write to 'system' table */
     public static final String CALL_METHOD_PUT_SYSTEM = "PUT_system";
 
@@ -1701,15 +1706,18 @@
     /** @hide - Private call() method to delete from the 'global' table */
     public static final String CALL_METHOD_DELETE_GLOBAL = "DELETE_global";
 
+    /** @hide - Private call() method to reset to defaults the 'configuration' table */
+    public static final String CALL_METHOD_DELETE_CONFIG = "DELETE_config";
+
+    /** @hide - Private call() method to reset to defaults the 'secure' table */
+    public static final String CALL_METHOD_RESET_SECURE = "RESET_secure";
+
     /** @hide - Private call() method to reset to defaults the 'global' table */
     public static final String CALL_METHOD_RESET_GLOBAL = "RESET_global";
 
     /** @hide - Private call() method to reset to defaults the 'configuration' table */
     public static final String CALL_METHOD_RESET_CONFIG = "RESET_config";
 
-    /** @hide - Private call() method to reset to defaults the 'secure' table */
-    public static final String CALL_METHOD_RESET_SECURE = "RESET_secure";
-
     /** @hide - Private call() method to query the 'system' table */
     public static final String CALL_METHOD_LIST_SYSTEM = "LIST_system";
 
@@ -1719,6 +1727,9 @@
     /** @hide - Private call() method to query the 'global' table */
     public static final String CALL_METHOD_LIST_GLOBAL = "LIST_global";
 
+    /** @hide - Private call() method to reset to defaults the 'configuration' table */
+    public static final String CALL_METHOD_LIST_CONFIG = "LIST_config";
+
     /**
      * Activity Extra: Limit available options in launched activity based on the given authority.
      * <p>
@@ -2044,7 +2055,8 @@
                     arg.putBoolean(CALL_METHOD_MAKE_DEFAULT_KEY, true);
                 }
                 IContentProvider cp = mProviderHolder.getProvider(cr);
-                cp.call(cr.getPackageName(), mCallSetCommand, name, arg);
+                cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(),
+                        mCallSetCommand, name, arg);
             } catch (RemoteException e) {
                 Log.w(TAG, "Can't set key " + name + " in " + mUri, e);
                 return false;
@@ -2117,12 +2129,14 @@
                     if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) {
                         final long token = Binder.clearCallingIdentity();
                         try {
-                            b = cp.call(cr.getPackageName(), mCallGetCommand, name, args);
+                            b = cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(),
+                                    mCallGetCommand, name, args);
                         } finally {
                             Binder.restoreCallingIdentity(token);
                         }
                     } else {
-                        b = cp.call(cr.getPackageName(), mCallGetCommand, name, args);
+                        b = cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(),
+                                mCallGetCommand, name, args);
                     }
                     if (b != null) {
                         String value = b.getString(Settings.NameValueTable.VALUE);
@@ -5112,7 +5126,8 @@
                 }
                 arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode);
                 IContentProvider cp = sProviderHolder.getProvider(resolver);
-                cp.call(resolver.getPackageName(), CALL_METHOD_RESET_SECURE, null, arg);
+                cp.call(resolver.getPackageName(), sProviderHolder.mUri.getAuthority(),
+                        CALL_METHOD_RESET_SECURE, null, arg);
             } catch (RemoteException e) {
                 Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e);
             }
@@ -11863,10 +11878,26 @@
         public static final String GPU_DEBUG_APP = "gpu_debug_app";
 
         /**
-         * App should try to use ANGLE
+         * Force all PKGs to use ANGLE, regardless of any other settings
+         * The value is a boolean (1 or 0).
          * @hide
          */
-        public static final String ANGLE_ENABLED_APP = "angle_enabled_app";
+        public static final String GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE =
+                "angle_gl_driver_all_angle";
+
+        /**
+         * List of PKGs that have an OpenGL driver selected
+         * @hide
+         */
+        public static final String GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS =
+                "angle_gl_driver_selection_pkgs";
+
+        /**
+         * List of selected OpenGL drivers, corresponding to the PKGs in GLOBAL_SETTINGS_DRIVER_PKGS
+         * @hide
+         */
+        public static final String GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES =
+                "angle_gl_driver_selection_values";
 
         /**
          * App that is selected to use updated graphics driver.
@@ -12840,7 +12871,7 @@
 
         /**
          * Property used by {@code com.android.server.SystemServer} on start to decide whether
-         * the Smart Suggestions service should be created or not
+         * the Content Capture service should be created or not
          *
          * <p>By default it should *NOT* be set (in which case the decision is based on whether
          * the OEM provides an implementation for the service), but it can be overridden to:
@@ -12852,8 +12883,8 @@
          *
          * @hide
          */
-        public static final String SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED =
-                "smart_suggestions_service_explicitly_enabled";
+        public static final String CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED =
+                "content_capture_service_explicitly_enabled";
 
         /**
          * Settings to backup. This is here so that it's in the same place as the settings
@@ -13147,7 +13178,8 @@
                 }
                 arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode);
                 IContentProvider cp = sProviderHolder.getProvider(resolver);
-                cp.call(resolver.getPackageName(), CALL_METHOD_RESET_GLOBAL, null, arg);
+                cp.call(resolver.getPackageName(), sProviderHolder.mUri.getAuthority(),
+                        CALL_METHOD_RESET_GLOBAL, null, arg);
             } catch (RemoteException e) {
                 Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e);
             }
@@ -13671,6 +13703,22 @@
                 "smart_replies_in_notifications_flags";
 
         /**
+         * Configuration flags for the automatic generation of smart replies and smart actions in
+         * notifications. This is encoded as a key=value list, separated by commas. Ex:
+         * "generate_replies=false,generate_actions=true".
+         *
+         * The following keys are supported:
+         *
+         * <pre>
+         * generate_replies                 (boolean)
+         * generate_actions                 (boolean)
+         * </pre>
+         * @hide
+         */
+        public static final String SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS =
+                "smart_suggestions_in_notifications_flags";
+
+        /**
          * If nonzero, crashes in foreground processes will bring up a dialog.
          * Otherwise, the process will be silently killed.
          * @hide
@@ -13747,6 +13795,14 @@
                 "backup_agent_timeout_parameters";
 
         /**
+         * Whether the backup system service supports multiple users (0 = disabled, 1 = enabled). If
+         * disabled, the service will only be active for the system user.
+         *
+         * @hide
+         */
+        public static final String BACKUP_MULTI_USER_ENABLED = "backup_multi_user_enabled";
+
+        /**
          * Blacklist of GNSS satellites.
          *
          * This is a list of integers separated by commas to represent pairs of (constellation,
@@ -13926,7 +13982,8 @@
                 }
                 arg.putInt(CALL_METHOD_RESET_MODE_KEY, RESET_MODE_PACKAGE_DEFAULTS);
                 IContentProvider cp = sProviderHolder.getProvider(resolver);
-                cp.call(resolver.getPackageName(), CALL_METHOD_RESET_CONFIG, null, arg);
+                cp.call(resolver.getPackageName(), sProviderHolder.mUri.getAuthority(),
+                        CALL_METHOD_RESET_CONFIG, null, arg);
             } catch (RemoteException e) {
                 Log.w(TAG, "Can't reset to defaults for " + CONTENT_URI, e);
             }
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 573d577..f39ef9a 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -618,7 +618,7 @@
         if (SERVICE_INTERFACE.equals(intent.getAction())) {
             return mInterface.asBinder();
         }
-        Log.w(TAG, "Tried to bind to wrong intent: " + intent);
+        Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
         return null;
     }
 
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
new file mode 100644
index 0000000..68a86f3
--- /dev/null
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.autofill.augmented;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.CallSuper;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
+import android.service.autofill.augmented.PresentationParams.SystemPopupPresentationParams;
+import android.util.Log;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TimeUtils;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+import android.view.autofill.IAugmentedAutofillManagerClient;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A service used to augment the Autofill subsystem by potentially providing autofill data when the
+ * "standard" workflow failed (for example, because the standard AutofillService didn't have data).
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class AugmentedAutofillService extends Service {
+
+    private static final String TAG = AugmentedAutofillService.class.getSimpleName();
+
+    // TODO(b/111330312): STOPSHIP use dynamic value, or change to false
+    static final boolean DEBUG = true;
+    static final boolean VERBOSE = false;
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     * To be supported, the service must also require the
+     * {@link android.Manifest.permission#BIND_AUGMENTED_AUTOFILL_SERVICE} permission so
+     * that other applications can not abuse it.
+     */
+    public static final String SERVICE_INTERFACE =
+            "android.service.autofill.augmented.AugmentedAutofillService";
+
+    private Handler mHandler;
+
+    private SparseArray<AutofillProxy> mAutofillProxies;
+
+    private final IAugmentedAutofillService mInterface = new IAugmentedAutofillService.Stub() {
+
+        @Override
+        public void onFillRequest(int sessionId, IBinder client, int taskId,
+                ComponentName componentName, AutofillId focusedId, AutofillValue focusedValue,
+                long requestTime, IFillCallback callback) {
+            mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnFillRequest,
+                    AugmentedAutofillService.this, sessionId, client, taskId, componentName,
+                    focusedId, focusedValue, requestTime, callback));
+        }
+
+        @Override
+        public void onDestroyFillWindowRequest(int sessionId) {
+            mHandler.sendMessage(
+                    obtainMessage(AugmentedAutofillService::handleOnDestroyFillWindowRequest,
+                            AugmentedAutofillService.this, sessionId));
+        }
+    };
+
+    @CallSuper
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mHandler = new Handler(Looper.getMainLooper(), null, true);
+    }
+
+    /** @hide */
+    @Override
+    public final IBinder onBind(Intent intent) {
+        if (SERVICE_INTERFACE.equals(intent.getAction())) {
+            return mInterface.asBinder();
+        }
+        Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
+        return null;
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnUnbind,
+                AugmentedAutofillService.this));
+        return false;
+    }
+
+    // TODO(b/111330312): add methods to disable autofill per app / activity?
+
+    /**
+     * Asks the service to handle an "augmented" autofill request.
+     *
+     * <p>This method is called when the "stantard" autofill service cannot handle a request, which
+     * typically occurs when:
+     * <ul>
+     *   <li>Service does not recognize what should be autofilled.
+     *   <li>Service does not have data to fill the request.
+     *   <li>Service blacklisted that app (or activity) for autofill.
+     *   <li>App disabled itself for autofill.
+     * </ul>
+     *
+     * <p>Differently from the standard autofill workflow, on augmented autofill the service is
+     * responsible to generate the autofill UI and request the Android system to autofill the
+     * activity when the user taps an action in that UI (through the
+     * {@link FillController#autofill(List)} method).
+     *
+     * <p>The service <b>MUST</b> call {@link
+     * FillCallback#onSuccess(android.service.autofill.augmented.FillResponse)} as soon as possible,
+     * passing {@code null} when it cannot fulfill the request.
+     * @param request the request to handle.
+     * @param cancellationSignal signal for observing cancellation requests. The system will use
+     *     this to notify you that the fill result is no longer needed and you should stop
+     *     handling this fill request in order to save resources.
+     * @param controller object used to interact with the autofill system.
+     * @param callback object used to notify the result of the request. Service <b>must</b> call
+     * {@link FillCallback#onSuccess(android.service.autofill.augmented.FillResponse)}.
+     */
+    public void onFillRequest(@NonNull FillRequest request,
+            @NonNull CancellationSignal cancellationSignal, @NonNull FillController controller,
+            @NonNull FillCallback callback) {
+    }
+
+    private void handleOnFillRequest(int sessionId, @NonNull IBinder client, int taskId,
+            @NonNull ComponentName componentName, @NonNull AutofillId focusedId,
+            @Nullable AutofillValue focusedValue, long requestTime,
+            @NonNull IFillCallback callback) {
+        if (mAutofillProxies == null) {
+            mAutofillProxies = new SparseArray<>();
+        }
+        AutofillProxy proxy = mAutofillProxies.get(sessionId);
+        if (proxy == null) {
+            proxy = new AutofillProxy(sessionId, client, taskId, componentName, focusedId,
+                    focusedValue, requestTime, callback);
+            mAutofillProxies.put(sessionId,  proxy);
+        } else {
+            // TODO(b/111330312): figure out if it's ok to reuse the proxy; add logging
+            if (DEBUG) Log.d(TAG, "Reusing proxy for session " + sessionId);
+        }
+        // TODO(b/111330312): set cancellation signal
+        final CancellationSignal cancellationSignal = null;
+        onFillRequest(new FillRequest(proxy), cancellationSignal, new FillController(proxy),
+                new FillCallback(proxy));
+    }
+
+    private void handleOnDestroyFillWindowRequest(@NonNull int sessionId) {
+        AutofillProxy proxy = null;
+        if (mAutofillProxies != null) {
+            proxy = mAutofillProxies.get(sessionId);
+        }
+        if (proxy == null) {
+            // TODO(b/111330312): this might be fine, in which case we should logv it
+            Log.w(TAG, "No proxy for session " + sessionId);
+            return;
+        }
+        proxy.destroy();
+        mAutofillProxies.remove(sessionId);
+    }
+
+    private void handleOnUnbind() {
+        if (mAutofillProxies == null) {
+            if (DEBUG) Log.d(TAG, "onUnbind(): no proxy to destroy");
+            return;
+        }
+        final int size = mAutofillProxies.size();
+        if (DEBUG) Log.d(TAG, "onUnbind(): destroying " + size + " proxies");
+        for (int i = 0; i < size; i++) {
+            final AutofillProxy proxy = mAutofillProxies.valueAt(i);
+            try {
+                proxy.destroy();
+            } catch (Exception e) {
+                Log.w(TAG, "error destroying " + proxy);
+            }
+        }
+        mAutofillProxies = null;
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mAutofillProxies != null) {
+            final int size = mAutofillProxies.size();
+            pw.print("Number proxies: "); pw.println(size);
+            for (int i = 0; i < size; i++) {
+                final int sessionId = mAutofillProxies.keyAt(i);
+                final AutofillProxy proxy = mAutofillProxies.valueAt(i);
+                pw.print(i); pw.print(") SessionId="); pw.print(sessionId); pw.println(":");
+                proxy.dump("  ", pw);
+            }
+        }
+    }
+
+    /** @hide */
+    static final class AutofillProxy {
+
+        static final int REPORT_EVENT_ON_SUCCESS = 1;
+        static final int REPORT_EVENT_UI_SHOWN = 2;
+        static final int REPORT_EVENT_UI_DESTROYED = 3;
+
+        @IntDef(prefix = { "REPORT_EVENT_" }, value = {
+                REPORT_EVENT_ON_SUCCESS,
+                REPORT_EVENT_UI_SHOWN,
+                REPORT_EVENT_UI_DESTROYED
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        @interface ReportEvent{}
+
+
+        private final Object mLock = new Object();
+        private final IAugmentedAutofillManagerClient mClient;
+        private final int mSessionId;
+        private final IFillCallback mCallback;
+        public final int taskId;
+        public final ComponentName componentName;
+        public final AutofillId focusedId;
+        public final AutofillValue focusedValue;
+
+        // Objects used to log metrics
+        private final long mRequestTime;
+        private long mOnSuccessTime;
+        private long mUiFirstShownTime;
+        private long mUiFirstDestroyedTime;
+
+        @GuardedBy("mLock")
+        private SystemPopupPresentationParams mSmartSuggestion;
+
+        @GuardedBy("mLock")
+        private FillWindow mFillWindow;
+
+        private AutofillProxy(int sessionId, @NonNull IBinder client, int taskId,
+                @NonNull ComponentName componentName, @NonNull AutofillId focusedId,
+                @Nullable AutofillValue focusedValue, long requestTime,
+                @NonNull IFillCallback callback) {
+            mSessionId = sessionId;
+            mClient = IAugmentedAutofillManagerClient.Stub.asInterface(client);
+            mCallback = callback;
+            this.taskId = taskId;
+            this.componentName = componentName;
+            this.focusedId = focusedId;
+            this.focusedValue = focusedValue;
+            this.mRequestTime = requestTime;
+            // TODO(b/111330312): linkToDeath
+        }
+
+        @NonNull
+        public SystemPopupPresentationParams getSmartSuggestionParams() {
+            synchronized (mLock) {
+                if (mSmartSuggestion != null) {
+                    return mSmartSuggestion;
+                }
+                Rect rect;
+                try {
+                    rect = mClient.getViewCoordinates(focusedId);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Could not get coordinates for " + focusedId);
+                    return null;
+                }
+                if (rect == null) {
+                    if (DEBUG) Log.d(TAG, "getViewCoordinates(" + focusedId + ") returned null");
+                    return null;
+                }
+                mSmartSuggestion = new SystemPopupPresentationParams(this, rect);
+                return mSmartSuggestion;
+            }
+        }
+
+        public void autofill(@NonNull List<Pair<AutofillId, AutofillValue>> pairs)
+                throws RemoteException {
+            final int size = pairs.size();
+            final List<AutofillId> ids = new ArrayList<>(size);
+            final List<AutofillValue> values = new ArrayList<>(size);
+            for (int i = 0; i < size; i++) {
+                final Pair<AutofillId, AutofillValue> pair = pairs.get(i);
+                ids.add(pair.first);
+                values.add(pair.second);
+            }
+            mClient.autofill(mSessionId, ids, values);
+        }
+
+        public void setFillWindow(@NonNull FillWindow fillWindow) {
+            synchronized (mLock) {
+                mFillWindow = fillWindow;
+            }
+        }
+
+        public FillWindow getFillWindow() {
+            synchronized (mLock) {
+                return mFillWindow;
+            }
+        }
+
+        // Used (mostly) for metrics.
+        public void report(@ReportEvent int event) {
+            switch (event) {
+                case REPORT_EVENT_ON_SUCCESS:
+                    if (mOnSuccessTime == 0) {
+                        mOnSuccessTime = SystemClock.elapsedRealtime();
+                        if (DEBUG) {
+                            Slog.d(TAG, "Service responsed in "
+                                    + TimeUtils.formatDuration(mOnSuccessTime - mRequestTime));
+                        }
+                    }
+                    try {
+                        mCallback.onSuccess();
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Error reporting success: " + e);
+                    }
+                    break;
+                case REPORT_EVENT_UI_SHOWN:
+                    if (mUiFirstShownTime == 0) {
+                        mUiFirstShownTime = SystemClock.elapsedRealtime();
+                        if (DEBUG) {
+                            Slog.d(TAG, "UI shown in "
+                                    + TimeUtils.formatDuration(mUiFirstShownTime - mRequestTime));
+                        }
+                    }
+                    break;
+                case REPORT_EVENT_UI_DESTROYED:
+                    if (mUiFirstDestroyedTime == 0) {
+                        mUiFirstDestroyedTime = SystemClock.elapsedRealtime();
+                        if (DEBUG) {
+                            Slog.d(TAG, "UI destroyed in "
+                                    + TimeUtils.formatDuration(
+                                            mUiFirstDestroyedTime - mRequestTime));
+                        }
+                    }
+                    break;
+                default:
+                    Slog.w(TAG, "invalid event reported: " + event);
+            }
+            // TODO(b/111330312): log metrics as well
+        }
+
+        public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
+            pw.print(prefix); pw.print("sessionId: "); pw.println(mSessionId);
+            pw.print(prefix); pw.print("taskId: "); pw.println(taskId);
+            pw.print(prefix); pw.print("component: ");
+            pw.println(componentName.flattenToShortString());
+            pw.print(prefix); pw.print("focusedId: "); pw.println(focusedId);
+            if (focusedValue != null) {
+                pw.print(prefix); pw.print("focusedValue: "); pw.println(focusedValue);
+            }
+            pw.print(prefix); pw.print("client: "); pw.println(mClient);
+            final String prefix2 = prefix + "  ";
+            if (mFillWindow != null) {
+                pw.print(prefix); pw.println("window:");
+                mFillWindow.dump(prefix2, pw);
+            }
+            if (mSmartSuggestion != null) {
+                pw.print(prefix); pw.println("smartSuggestion:");
+                mSmartSuggestion.dump(prefix2, pw);
+            }
+            if (mOnSuccessTime > 0) {
+                final long responseTime = mOnSuccessTime - mRequestTime;
+                pw.print(prefix); pw.print("response time: ");
+                TimeUtils.formatDuration(responseTime, pw); pw.println();
+            }
+
+            if (mUiFirstShownTime > 0) {
+                final long uiRenderingTime = mUiFirstShownTime - mRequestTime;
+                pw.print(prefix); pw.print("UI rendering time: ");
+                TimeUtils.formatDuration(uiRenderingTime, pw); pw.println();
+            }
+
+            if (mUiFirstDestroyedTime > 0) {
+                final long uiTotalTime = mUiFirstDestroyedTime - mRequestTime;
+                pw.print(prefix); pw.print("UI life time: ");
+                TimeUtils.formatDuration(uiTotalTime, pw); pw.println();
+            }
+        }
+
+        private void destroy() {
+            synchronized (mLock) {
+                if (mFillWindow != null) {
+                    if (DEBUG) Log.d(TAG, "destroying window");
+                    mFillWindow.destroy();
+                }
+            }
+        }
+    }
+}
diff --git a/core/java/android/service/intelligence/FillCallback.java b/core/java/android/service/autofill/augmented/FillCallback.java
similarity index 92%
rename from core/java/android/service/intelligence/FillCallback.java
rename to core/java/android/service/autofill/augmented/FillCallback.java
index ddf37f7..0546465 100644
--- a/core/java/android/service/intelligence/FillCallback.java
+++ b/core/java/android/service/autofill/augmented/FillCallback.java
@@ -13,12 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.intelligence;
+package android.service.autofill.augmented;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
 
 /**
  * Callback used to indicate at {@link FillRequest} has been fulfilled.
diff --git a/core/java/android/service/intelligence/FillController.java b/core/java/android/service/autofill/augmented/FillController.java
similarity index 90%
rename from core/java/android/service/intelligence/FillController.java
rename to core/java/android/service/autofill/augmented/FillController.java
index 4a9c85d..e65cf47 100644
--- a/core/java/android/service/intelligence/FillController.java
+++ b/core/java/android/service/autofill/augmented/FillController.java
@@ -13,14 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.intelligence;
+package android.service.autofill.augmented;
 
-import static android.service.intelligence.SmartSuggestionsService.DEBUG;
+import static android.service.autofill.augmented.AugmentedAutofillService.DEBUG;
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.RemoteException;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
 import android.util.Log;
 import android.util.Pair;
 import android.view.autofill.AutofillId;
diff --git a/core/java/android/service/intelligence/FillRequest.java b/core/java/android/service/autofill/augmented/FillRequest.java
similarity index 71%
rename from core/java/android/service/intelligence/FillRequest.java
rename to core/java/android/service/autofill/augmented/FillRequest.java
index 53e99a5..fd75b15 100644
--- a/core/java/android/service/intelligence/FillRequest.java
+++ b/core/java/android/service/autofill/augmented/FillRequest.java
@@ -13,12 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.intelligence;
+package android.service.autofill.augmented;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.content.ComponentName;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 
@@ -27,6 +28,7 @@
  * @hide
  */
 @SystemApi
+// TODO(b/111330312): pass a requestId and/or sessionId
 public final class FillRequest {
 
     final AutofillProxy mProxy;
@@ -37,11 +39,18 @@
     }
 
     /**
-     * Gets the session associated with this request.
+     * Gets the task of the activity associated with this request.
+     */
+    public int getTaskId() {
+        return mProxy.taskId;
+    }
+
+    /**
+     * Gets the name of the activity associated with this request.
      */
     @NonNull
-    public InteractionSessionId getSessionId() {
-        return mProxy.sessionId;
+    public ComponentName getActivityComponent() {
+        return mProxy.componentName;
     }
 
     /**
@@ -56,7 +65,7 @@
      * Gets the current value of the field that triggered the request.
      */
     @NonNull
-    public AutofillValue getFocusedAutofillValue() {
+    public AutofillValue getFocusedValue() {
         return mProxy.focusedValue;
     }
 
@@ -72,6 +81,7 @@
 
     @Override
     public String toString() {
-        return "FillRequest[id=" + mProxy.focusedId + "]";
+        return "FillRequest[act=" + getActivityComponent().flattenToShortString()
+                + ", id=" + mProxy.focusedId + "]";
     }
 }
diff --git a/core/java/android/service/intelligence/FillResponse.java b/core/java/android/service/autofill/augmented/FillResponse.java
similarity index 97%
rename from core/java/android/service/intelligence/FillResponse.java
rename to core/java/android/service/autofill/augmented/FillResponse.java
index 860c027..7064b6f 100644
--- a/core/java/android/service/intelligence/FillResponse.java
+++ b/core/java/android/service/autofill/augmented/FillResponse.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.intelligence;
+package android.service.autofill.augmented;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -50,7 +50,7 @@
      * @hide
      */
     @SystemApi
-    public static class Builder {
+    public static final class Builder {
 
         private FillWindow mFillWindow;
 
diff --git a/core/java/android/service/intelligence/FillWindow.java b/core/java/android/service/autofill/augmented/FillWindow.java
similarity index 85%
rename from core/java/android/service/intelligence/FillWindow.java
rename to core/java/android/service/autofill/augmented/FillWindow.java
index 39d7e08..27df845 100644
--- a/core/java/android/service/intelligence/FillWindow.java
+++ b/core/java/android/service/autofill/augmented/FillWindow.java
@@ -13,19 +13,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.intelligence;
+package android.service.autofill.augmented;
 
-import static android.service.intelligence.SmartSuggestionsService.DEBUG;
+import static android.service.autofill.augmented.AugmentedAutofillService.DEBUG;
 
 import android.annotation.LongDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.app.Dialog;
 import android.graphics.Rect;
-import android.service.intelligence.PresentationParams.Area;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
+import android.service.autofill.augmented.PresentationParams.Area;
 import android.util.Log;
 import android.view.Gravity;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
@@ -60,7 +61,7 @@
  * @hide
  */
 @SystemApi
-public final class FillWindow {
+public final class FillWindow implements AutoCloseable {
     private static final String TAG = "FillWindow";
 
     /** Indicates the data being shown is a physical address */
@@ -140,10 +141,24 @@
             // TODO(b/111330312): make sure all touch events are handled, window is always closed,
             // etc.
 
-            mDialog = new Dialog(rootView.getContext());
+            mDialog = new Dialog(rootView.getContext()) {
+                @Override
+                public boolean onTouchEvent(MotionEvent event) {
+                    if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+                        FillWindow.this.destroy();
+                    }
+                    return false;
+                }
+            };
             mCloseGuard.open("destroy");
             final Window window = mDialog.getWindow();
             window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
+            // Makes sure touch outside the dialog is received by the window behind the dialog.
+            window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
+            // Makes sure the touch outside the dialog is received by the dialog to dismiss it.
+            window.addFlags(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
+            // Makes sure keyboard shows up.
+            window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
 
             final int height = rect.bottom - rect.top;
             final int width = rect.right - rect.left;
@@ -238,4 +253,10 @@
             }
         }
     }
+
+    /** @hide */
+    @Override
+    public void close() throws Exception {
+        destroy();
+    }
 }
diff --git a/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
new file mode 100644
index 0000000..b3ac2da1
--- /dev/null
+++ b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill.augmented;
+
+import android.content.ComponentName;
+import android.os.IBinder;
+
+import android.service.autofill.augmented.IFillCallback;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+
+import java.util.List;
+
+/**
+ * Interface from the system to an Augmented Autofill service.
+ *
+ * @hide
+ */
+oneway interface IAugmentedAutofillService {
+
+    void onFillRequest(int sessionId, in IBinder autofillManagerClient, int taskId,
+                       in ComponentName activityComponent, in AutofillId focusedId,
+                       in AutofillValue focusedValue, long requestTime, in IFillCallback callback);
+
+    void onDestroyFillWindowRequest(int sessionId);
+}
diff --git a/core/java/android/service/autofill/augmented/IFillCallback.aidl b/core/java/android/service/autofill/augmented/IFillCallback.aidl
new file mode 100644
index 0000000..dac7590
--- /dev/null
+++ b/core/java/android/service/autofill/augmented/IFillCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill.augmented;
+
+import android.os.ICancellationSignal;
+
+/**
+ * Interface to receive the result of an autofill request.
+ *
+ * @hide
+ */
+interface IFillCallback {
+    // TODO(b/111330312): add cancellation (after we have CTS tests, so we can test it)
+//    void onCancellable(in ICancellationSignal cancellation);
+    // TODO(b/111330312): might need to pass the response (once IME implements Smart Suggestions)
+    void onSuccess();
+}
diff --git a/core/java/android/service/intelligence/PresentationParams.java b/core/java/android/service/autofill/augmented/PresentationParams.java
similarity index 95%
rename from core/java/android/service/intelligence/PresentationParams.java
rename to core/java/android/service/autofill/augmented/PresentationParams.java
index 9530309..0124ecc 100644
--- a/core/java/android/service/intelligence/PresentationParams.java
+++ b/core/java/android/service/autofill/augmented/PresentationParams.java
@@ -13,14 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.intelligence;
+package android.service.autofill.augmented;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.graphics.Rect;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
 import android.util.DebugUtils;
 import android.view.View;
 
@@ -174,11 +174,12 @@
          *
          * @param bounds boundaries relative to this Area.
          *
-         * @throws {@link IllegalArgumentException} if the {@code bounds} is not fully-contained
-         * inside this full Area.
-         *
          * @return new subarea, or {@code null} if the Smart Suggestion host does not support such
          * subaarea.
+         *
+         * @throws IllegalArgumentException if the {@code bounds} is not fully-contained inside this
+         * full Area.
+         *
          */
         @Nullable
         public Area getSubArea(@NonNull Rect bounds) {
diff --git a/core/java/android/service/intelligence/ContentCaptureEventsRequest.aidl b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl
similarity index 94%
rename from core/java/android/service/intelligence/ContentCaptureEventsRequest.aidl
rename to core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl
index 23d607d..c032cfdb 100644
--- a/core/java/android/service/intelligence/ContentCaptureEventsRequest.aidl
+++ b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.intelligence;
+package android.service.contentcapture;
 
 parcelable ContentCaptureEventsRequest;
diff --git a/core/java/android/service/intelligence/ContentCaptureEventsRequest.java b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java
similarity index 95%
rename from core/java/android/service/intelligence/ContentCaptureEventsRequest.java
rename to core/java/android/service/contentcapture/ContentCaptureEventsRequest.java
index bc5b92b..df58f52 100644
--- a/core/java/android/service/intelligence/ContentCaptureEventsRequest.java
+++ b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java
@@ -13,13 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.intelligence;
+package android.service.contentcapture;
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.view.intelligence.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureEvent;
 
 import java.util.List;
 
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
new file mode 100644
index 0000000..3dfeede
--- /dev/null
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.contentcapture;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.CallSuper;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.contentcapture.ContentCaptureEvent;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A service used to capture the content of the screen to provide contextual data in other areas of
+ * the system such as Autofill.
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class ContentCaptureService extends Service {
+
+    private static final String TAG = ContentCaptureService.class.getSimpleName();
+
+    // TODO(b/111330312): STOPSHIP use dynamic value, or change to false
+    static final boolean DEBUG = true;
+    static final boolean VERBOSE = false;
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     *
+     * <p>To be supported, the service must also require the
+     * {@link android.Manifest.permission#BIND_CONTENT_CAPTURE_SERVICE} permission so
+     * that other applications can not abuse it.
+     */
+    public static final String SERVICE_INTERFACE =
+            "android.service.contentcapture.ContentCaptureService";
+
+    private Handler mHandler;
+
+    private final IContentCaptureService mInterface = new IContentCaptureService.Stub() {
+
+        @Override
+        public void onSessionLifecycle(InteractionContext context, String sessionId)
+                throws RemoteException {
+            if (context != null) {
+                mHandler.sendMessage(
+                        obtainMessage(ContentCaptureService::handleOnCreateInteractionSession,
+                                ContentCaptureService.this, context, sessionId));
+            } else {
+                mHandler.sendMessage(
+                        obtainMessage(ContentCaptureService::handleOnDestroyInteractionSession,
+                                ContentCaptureService.this, sessionId));
+            }
+        }
+
+        @Override
+        public void onContentCaptureEventsRequest(String sessionId,
+                ContentCaptureEventsRequest request) {
+            mHandler.sendMessage(
+                    obtainMessage(ContentCaptureService::handleOnContentCaptureEventsRequest,
+                            ContentCaptureService.this, sessionId, request));
+
+        }
+
+        @Override
+        public void onActivitySnapshot(String sessionId, SnapshotData snapshotData) {
+            mHandler.sendMessage(
+                    obtainMessage(ContentCaptureService::handleOnActivitySnapshot,
+                            ContentCaptureService.this, sessionId, snapshotData));
+        }
+    };
+
+    @CallSuper
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mHandler = new Handler(Looper.getMainLooper(), null, true);
+    }
+
+    /** @hide */
+    @Override
+    public final IBinder onBind(Intent intent) {
+        if (SERVICE_INTERFACE.equals(intent.getAction())) {
+            return mInterface.asBinder();
+        }
+        Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
+        return null;
+    }
+
+    /**
+     * Explicitly limits content capture to the given packages and activities.
+     *
+     * <p>When the whitelist is set, it overrides the values passed to
+     * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}
+     * and {@link #setPackageContentCaptureEnabled(String, boolean)}.
+     *
+     * <p>To reset the whitelist, call it passing {@code null} to both arguments.
+     *
+     * <p>Useful when the service wants to restrict content capture to a category of apps, like
+     * chat apps. For example, if the service wants to support view captures on all activities of
+     * app {@code ChatApp1} and just activities {@code act1} and {@code act2} of {@code ChatApp2},
+     * it would call: {@code setContentCaptureWhitelist(Arrays.asList("ChatApp1"),
+     * Arrays.asList(new ComponentName("ChatApp2", "act1"),
+     * new ComponentName("ChatApp2", "act2")));}
+     */
+    public final void setContentCaptureWhitelist(@Nullable List<String> packages,
+            @Nullable List<ComponentName> activities) {
+        //TODO(b/111276913): implement
+    }
+
+    /**
+     * Defines whether content capture should be enabled for activities with such
+     * {@link android.content.ComponentName}.
+     *
+     * <p>Useful to blacklist a particular activity.
+     */
+    public final void setActivityContentCaptureEnabled(@NonNull ComponentName activity,
+            boolean enabled) {
+        //TODO(b/111276913): implement
+    }
+
+    /**
+     * Defines whether content capture should be enabled for activities of the app with such
+     * {@code packageName}.
+     *
+     * <p>Useful to blacklist any activity from a particular app.
+     */
+    public final void setPackageContentCaptureEnabled(@NonNull String packageName,
+            boolean enabled) {
+        //TODO(b/111276913): implement
+    }
+
+    /**
+     * Gets the activities where content capture was disabled by
+     * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}.
+     */
+    @NonNull
+    public final Set<ComponentName> getContentCaptureDisabledActivities() {
+        //TODO(b/111276913): implement
+        return null;
+    }
+
+    /**
+     * Gets the apps where content capture was disabled by
+     * {@link #setPackageContentCaptureEnabled(String, boolean)}.
+     */
+    @NonNull
+    public final Set<String> getContentCaptureDisabledPackages() {
+        //TODO(b/111276913): implement
+        return null;
+    }
+
+    /**
+     * Creates a new interaction session.
+     *
+     * @param context interaction context
+     * @param sessionId the session's Id
+     */
+    public void onCreateInteractionSession(@NonNull InteractionContext context,
+            @NonNull InteractionSessionId sessionId) {
+        if (VERBOSE) {
+            Log.v(TAG, "onCreateInteractionSession(id=" + sessionId + ", ctx=" + context + ")");
+        }
+    }
+
+    /**
+     * Notifies the service of {@link ContentCaptureEvent events} associated with a content capture
+     * session.
+     *
+     * @param sessionId the session's Id
+     * @param request the events
+     */
+    public abstract void onContentCaptureEventsRequest(@NonNull InteractionSessionId sessionId,
+            @NonNull ContentCaptureEventsRequest request);
+
+    /**
+     * Notifies the service of {@link SnapshotData snapshot data} associated with a session.
+     *
+     * @param sessionId the session's Id
+     * @param snapshotData the data
+     */
+    public void onActivitySnapshot(@NonNull InteractionSessionId sessionId,
+            @NonNull SnapshotData snapshotData) {}
+
+    /**
+     * Destroys the interaction session.
+     *
+     * @param sessionId the id of the session to destroy
+     */
+    public void onDestroyInteractionSession(@NonNull InteractionSessionId sessionId) {
+        if (VERBOSE) {
+            Log.v(TAG, "onDestroyInteractionSession(id=" + sessionId + ")");
+        }
+    }
+
+    //TODO(b/111276913): consider caching the InteractionSessionId for the lifetime of the session,
+    // so we don't need to create a temporary InteractionSessionId for each event.
+
+    private void handleOnCreateInteractionSession(@NonNull InteractionContext context,
+            @NonNull String sessionId) {
+        onCreateInteractionSession(context, new InteractionSessionId(sessionId));
+    }
+
+    private void handleOnContentCaptureEventsRequest(@NonNull String sessionId,
+            @NonNull ContentCaptureEventsRequest request) {
+        onContentCaptureEventsRequest(new InteractionSessionId(sessionId), request);
+    }
+
+    private void handleOnActivitySnapshot(@NonNull String sessionId,
+            @NonNull SnapshotData snapshotData) {
+        onActivitySnapshot(new InteractionSessionId(sessionId), snapshotData);
+    }
+
+    private void handleOnDestroyInteractionSession(@NonNull String sessionId) {
+        onDestroyInteractionSession(new InteractionSessionId(sessionId));
+    }
+}
diff --git a/core/java/android/service/contentcapture/IContentCaptureService.aidl b/core/java/android/service/contentcapture/IContentCaptureService.aidl
new file mode 100644
index 0000000..29e9abb
--- /dev/null
+++ b/core/java/android/service/contentcapture/IContentCaptureService.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.contentcapture;
+
+import android.service.contentcapture.ContentCaptureEventsRequest;
+import android.service.contentcapture.InteractionContext;
+import android.service.contentcapture.SnapshotData;
+
+import java.util.List;
+
+/**
+ * Interface from the system to a Content Capture service.
+ *
+ * @hide
+ */
+oneway interface IContentCaptureService {
+
+    // Called when session is created (context not null) or destroyed (context null)
+    void onSessionLifecycle(in InteractionContext context, String sessionId);
+
+    void onContentCaptureEventsRequest(String sessionId, in ContentCaptureEventsRequest request);
+
+    void onActivitySnapshot(String sessionId, in SnapshotData snapshotData);
+}
diff --git a/core/java/android/service/intelligence/InteractionContext.aidl b/core/java/android/service/contentcapture/InteractionContext.aidl
similarity index 93%
rename from core/java/android/service/intelligence/InteractionContext.aidl
rename to core/java/android/service/contentcapture/InteractionContext.aidl
index 4ce6aa4..982e095 100644
--- a/core/java/android/service/intelligence/InteractionContext.aidl
+++ b/core/java/android/service/contentcapture/InteractionContext.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.intelligence;
+package android.service.contentcapture;
 
 parcelable InteractionContext;
diff --git a/core/java/android/service/intelligence/InteractionContext.java b/core/java/android/service/contentcapture/InteractionContext.java
similarity index 96%
rename from core/java/android/service/intelligence/InteractionContext.java
rename to core/java/android/service/contentcapture/InteractionContext.java
index 7f4283d..f1281ff 100644
--- a/core/java/android/service/intelligence/InteractionContext.java
+++ b/core/java/android/service/contentcapture/InteractionContext.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.intelligence;
+package android.service.contentcapture;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -37,7 +37,7 @@
     /**
      * Flag used to indicate that the app explicitly disabled content capture for the activity
      * (using
-     * {@link android.view.intelligence.ContentCaptureManager#setContentCaptureEnabled()}),
+     * {@link android.view.contentcapture.ContentCaptureManager#setContentCaptureEnabled(boolean)}),
      * in which case the service will just receive activity-level events.
      */
     public static final int FLAG_DISABLED_BY_APP = 0x1;
diff --git a/core/java/android/service/intelligence/InteractionSessionId.java b/core/java/android/service/contentcapture/InteractionSessionId.java
similarity index 90%
rename from core/java/android/service/intelligence/InteractionSessionId.java
rename to core/java/android/service/contentcapture/InteractionSessionId.java
index 667193b..8411947 100644
--- a/core/java/android/service/intelligence/InteractionSessionId.java
+++ b/core/java/android/service/contentcapture/InteractionSessionId.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.service.intelligence;
+package android.service.contentcapture;
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
@@ -22,10 +22,12 @@
 import android.os.Parcelable;
 
 import java.io.PrintWriter;
-import java.util.UUID;
 
-// TODO(b/111276913): add javadocs / implement equals/hashcode/string
-/** @hide */
+/**
+ * Identifier for a Content Capture session.
+ *
+ * @hide
+ */
 @SystemApi
 public final class InteractionSessionId implements Parcelable {
 
@@ -34,15 +36,6 @@
     /**
      * Creates a new instance.
      *
-     * @hide
-     */
-    public InteractionSessionId() {
-        this(UUID.randomUUID().toString());
-    }
-
-    /**
-     * Creates a new instance.
-     *
      * @param value The internal value.
      *
      * @hide
diff --git a/core/java/android/service/intelligence/SnapshotData.aidl b/core/java/android/service/contentcapture/SnapshotData.aidl
similarity index 93%
rename from core/java/android/service/intelligence/SnapshotData.aidl
rename to core/java/android/service/contentcapture/SnapshotData.aidl
index 31d1339..a00e8526 100644
--- a/core/java/android/service/intelligence/SnapshotData.aidl
+++ b/core/java/android/service/contentcapture/SnapshotData.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.intelligence;
+package android.service.contentcapture;
 
 parcelable SnapshotData;
diff --git a/core/java/android/service/intelligence/SnapshotData.java b/core/java/android/service/contentcapture/SnapshotData.java
similarity index 98%
rename from core/java/android/service/intelligence/SnapshotData.java
rename to core/java/android/service/contentcapture/SnapshotData.java
index b9310ea..bc2116a 100644
--- a/core/java/android/service/intelligence/SnapshotData.java
+++ b/core/java/android/service/contentcapture/SnapshotData.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.service.intelligence;
+package android.service.contentcapture;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
diff --git a/core/java/android/service/intelligence/IIntelligenceService.aidl b/core/java/android/service/intelligence/IIntelligenceService.aidl
deleted file mode 100644
index 2b924fb..0000000
--- a/core/java/android/service/intelligence/IIntelligenceService.aidl
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.intelligence;
-
-import android.os.IBinder;
-import android.service.intelligence.ContentCaptureEventsRequest;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.InteractionContext;
-import android.service.intelligence.SnapshotData;
-
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.intelligence.ContentCaptureEvent;
-
-import java.util.List;
-
-/**
- * Interface from the system to an intelligence service.
- *
- * @hide
- */
- // TODO(b/111276913): rename / update javadoc (once the final name is defined)
-oneway interface IIntelligenceService {
-
-    // Called when session is created (context not null) or destroyed (context null)
-    void onSessionLifecycle(in InteractionContext context, in InteractionSessionId sessionId);
-
-    void onContentCaptureEventsRequest(in InteractionSessionId sessionId,
-                                in ContentCaptureEventsRequest request);
-
-    void onActivitySnapshot(in InteractionSessionId sessionId,
-                            in SnapshotData snapshotData);
-
-    void onAutofillRequest(in InteractionSessionId sessionId, in IBinder autofillManagerClient,
-                           int autofilSessionId, in AutofillId focusedId,
-                           in AutofillValue focusedValue, long requestTime);
-
-    void onDestroyAutofillWindowsRequest(in InteractionSessionId sessionId);
-}
diff --git a/core/java/android/service/intelligence/InteractionSessionId.aidl b/core/java/android/service/intelligence/InteractionSessionId.aidl
deleted file mode 100644
index a5392b6..0000000
--- a/core/java/android/service/intelligence/InteractionSessionId.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.intelligence;
-
-parcelable InteractionSessionId;
diff --git a/core/java/android/service/intelligence/SmartSuggestionsService.java b/core/java/android/service/intelligence/SmartSuggestionsService.java
deleted file mode 100644
index b684b02..0000000
--- a/core/java/android/service/intelligence/SmartSuggestionsService.java
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.service.intelligence;
-
-import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
-
-import android.annotation.CallSuper;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.app.Service;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.os.CancellationSignal;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.service.intelligence.PresentationParams.SystemPopupPresentationParams;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.Pair;
-import android.util.Slog;
-import android.util.TimeUtils;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAugmentedAutofillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * A service used to capture the content of the screen to provide contextual data in other areas of
- * the system such as Autofill.
- *
- * @hide
- */
-@SystemApi
-public abstract class SmartSuggestionsService extends Service {
-
-    private static final String TAG = "SmartSuggestionsService";
-
-    // TODO(b/111330312): STOPSHIP use dynamic value, or change to false
-    static final boolean DEBUG = true;
-    static final boolean VERBOSE = false;
-
-    /**
-     * The {@link Intent} that must be declared as handled by the service.
-     * To be supported, the service must also require the
-     * {@link android.Manifest.permission#BIND_SMART_SUGGESTIONS_SERVICE} permission so
-     * that other applications can not abuse it.
-     */
-    public static final String SERVICE_INTERFACE =
-            "android.service.intelligence.SmartSuggestionsService";
-
-    private Handler mHandler;
-
-    private ArrayMap<InteractionSessionId, AutofillProxy> mAutofillProxies;
-
-    private final IIntelligenceService mInterface = new IIntelligenceService.Stub() {
-
-        @Override
-        public void onSessionLifecycle(InteractionContext context, InteractionSessionId sessionId)
-                throws RemoteException {
-            if (context != null) {
-                mHandler.sendMessage(
-                        obtainMessage(SmartSuggestionsService::onCreateInteractionSession,
-                                SmartSuggestionsService.this, context, sessionId));
-            } else {
-                mHandler.sendMessage(
-                        obtainMessage(SmartSuggestionsService::onDestroyInteractionSession,
-                                SmartSuggestionsService.this, sessionId));
-            }
-        }
-
-        @Override
-        public void onContentCaptureEventsRequest(InteractionSessionId sessionId,
-                ContentCaptureEventsRequest request) {
-            mHandler.sendMessage(
-                    obtainMessage(SmartSuggestionsService::onContentCaptureEventsRequest,
-                            SmartSuggestionsService.this, sessionId, request));
-
-        }
-
-        @Override
-        public void onActivitySnapshot(InteractionSessionId sessionId,
-                SnapshotData snapshotData) {
-            mHandler.sendMessage(
-                    obtainMessage(SmartSuggestionsService::onActivitySnapshot,
-                            SmartSuggestionsService.this, sessionId, snapshotData));
-        }
-
-        @Override
-        public void onAutofillRequest(InteractionSessionId sessionId, IBinder client,
-                int autofilSessionId, AutofillId focusedId, AutofillValue focusedValue,
-                long requestTime) {
-            mHandler.sendMessage(obtainMessage(SmartSuggestionsService::handleOnAutofillRequest,
-                    SmartSuggestionsService.this, sessionId, client, autofilSessionId, focusedId,
-                    focusedValue, requestTime));
-        }
-
-        @Override
-        public void onDestroyAutofillWindowsRequest(InteractionSessionId sessionId) {
-            mHandler.sendMessage(
-                    obtainMessage(SmartSuggestionsService::handleOnDestroyAutofillWindowsRequest,
-                            SmartSuggestionsService.this, sessionId));
-        }
-    };
-
-    @CallSuper
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        mHandler = new Handler(Looper.getMainLooper(), null, true);
-    }
-
-    /** @hide */
-    @Override
-    public final IBinder onBind(Intent intent) {
-        if (SERVICE_INTERFACE.equals(intent.getAction())) {
-            return mInterface.asBinder();
-        }
-        Log.w(TAG, "Tried to bind to wrong intent: " + intent);
-        return null;
-    }
-
-    /**
-     * Explicitly limits content capture to the given packages and activities.
-     *
-     * <p>When the whitelist is set, it overrides the values passed to
-     * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}
-     * and {@link #setPackageContentCaptureEnabled(String, boolean)}.
-     *
-     * <p>To reset the whitelist, call it passing {@code null} to both arguments.
-     *
-     * <p>Useful when the service wants to restrict content capture to a category of apps, like
-     * chat apps. For example, if the service wants to support view captures on all activities of
-     * app {@code ChatApp1} and just activities {@code act1} and {@code act2} of {@code ChatApp2},
-     * it would call: {@code setContentCaptureWhitelist(Arrays.asList("ChatApp1"),
-     * Arrays.asList(new ComponentName("ChatApp2", "act1"),
-     * new ComponentName("ChatApp2", "act2")));}
-     */
-    public final void setContentCaptureWhitelist(@Nullable List<String> packages,
-            @Nullable List<ComponentName> activities) {
-        //TODO(b/111276913): implement
-    }
-
-    /**
-     * Defines whether content capture should be enabled for activities with such
-     * {@link android.content.ComponentName}.
-     *
-     * <p>Useful to blacklist a particular activity.
-     */
-    public final void setActivityContentCaptureEnabled(@NonNull ComponentName activity,
-            boolean enabled) {
-        //TODO(b/111276913): implement
-    }
-
-    /**
-     * Defines whether content capture should be enabled for activities of the app with such
-     * {@code packageName}.
-     *
-     * <p>Useful to blacklist any activity from a particular app.
-     */
-    public final void setPackageContentCaptureEnabled(@NonNull String packageName,
-            boolean enabled) {
-        //TODO(b/111276913): implement
-    }
-
-    /**
-     * Gets the activities where content capture was disabled by
-     * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}.
-     */
-    @NonNull
-    public final Set<ComponentName> getContentCaptureDisabledActivities() {
-        //TODO(b/111276913): implement
-        return null;
-    }
-
-    /**
-     * Gets the apps where content capture was disabled by
-     * {@link #setPackageContentCaptureEnabled(String, boolean)}.
-     */
-    @NonNull
-    public final Set<String> getContentCaptureDisabledPackages() {
-        //TODO(b/111276913): implement
-        return null;
-    }
-
-    /**
-     * Creates a new interaction session.
-     *
-     * @param context interaction context
-     * @param sessionId the session's Id
-     */
-    public void onCreateInteractionSession(@NonNull InteractionContext context,
-            @NonNull InteractionSessionId sessionId) {
-        if (VERBOSE) {
-            Log.v(TAG, "onCreateInteractionSession(id=" + sessionId + ", ctx=" + context + ")");
-        }
-    }
-
-    /**
-     * Notifies the service of {@link ContentCaptureEvent events} associated with a content capture
-     * session.
-     *
-     * @param sessionId the session's Id
-     * @param request the events
-     */
-    // TODO(b/111276913): rename to onContentCaptureEvents or something like that; also, pass a
-    // Request object so it can be extended
-    public abstract void onContentCaptureEventsRequest(@NonNull InteractionSessionId sessionId,
-            @NonNull ContentCaptureEventsRequest request);
-
-    private void handleOnAutofillRequest(@NonNull InteractionSessionId sessionId,
-            @NonNull IBinder client, int autofillSessionId, @NonNull AutofillId focusedId,
-            @Nullable AutofillValue focusedValue, long requestTime) {
-        if (mAutofillProxies == null) {
-            mAutofillProxies = new ArrayMap<>();
-        }
-        AutofillProxy proxy = mAutofillProxies.get(sessionId);
-        if (proxy == null) {
-            proxy = new AutofillProxy(sessionId, client, autofillSessionId, focusedId, focusedValue,
-                    requestTime);
-            mAutofillProxies.put(sessionId,  proxy);
-        } else {
-            // TODO(b/111330312): figure out if it's ok to reuse the proxy; add logging
-            if (DEBUG) Log.d(TAG, "Reusing proxy for session " + sessionId);
-        }
-        // TODO(b/111330312): set cancellation signal
-        final CancellationSignal cancellationSignal = null;
-        onFillRequest(sessionId, new FillRequest(proxy), cancellationSignal,
-                new FillController(proxy), new FillCallback(proxy));
-    }
-
-    /**
-     * Asks the service to handle an "augmented" autofill request.
-     *
-     * <p>This method is called when the "stantard" autofill service cannot handle a request, which
-     * typically occurs when:
-     * <ul>
-     *   <li>Service does not recognize what should be autofilled.
-     *   <li>Service does not have data to fill the request.
-     *   <li>Service blacklisted that app (or activity) for autofill.
-     *   <li>App disabled itself for autofill.
-     * </ul>
-     *
-     * <p>Differently from the standard autofill workflow, on augmented autofill the service is
-     * responsible to generate the autofill UI and request the Android system to autofill the
-     * activity when the user taps an action in that UI (through the
-     * {@link FillController#autofill(List)} method).
-     *
-     * <p>The service <b>MUST</b> call {@link
-     * FillCallback#onSuccess(android.service.intelligence.FillResponse)} as soon as possible,
-     * passing {@code null} when it cannot fulfill the request.
-     *
-     * @param sessionId the session's id
-     * @param request the request to handle.
-     * @param cancellationSignal signal for observing cancellation requests. The system will use
-     *     this to notify you that the fill result is no longer needed and you should stop
-     *     handling this fill request in order to save resources.
-     * @param controller object used to interact with the autofill system.
-     * @param callback object used to notify the result of the request. Service <b>must</b> call
-     * {@link FillCallback#onSuccess(android.service.intelligence.FillResponse)}.
-     */
-    public void onFillRequest(@NonNull InteractionSessionId sessionId, @NonNull FillRequest request,
-            @NonNull CancellationSignal cancellationSignal, @NonNull FillController controller,
-            @NonNull FillCallback callback) {
-    }
-
-    private void handleOnDestroyAutofillWindowsRequest(@NonNull InteractionSessionId sessionId) {
-        AutofillProxy proxy = null;
-        if (mAutofillProxies != null) {
-            proxy = mAutofillProxies.get(sessionId);
-        }
-        if (proxy == null) {
-            // TODO(b/111330312): this might be fine, in which case we should logv it
-            Log.w(TAG, "No proxy for session " + sessionId);
-            return;
-        }
-        proxy.destroy();
-        mAutofillProxies.remove(sessionId);
-    }
-
-    @Override
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mAutofillProxies != null) {
-            final int size = mAutofillProxies.size();
-            pw.print("Number proxies: "); pw.println(size);
-            for (int i = 0; i < size; i++) {
-                final InteractionSessionId sessionId = mAutofillProxies.keyAt(i);
-                final AutofillProxy proxy = mAutofillProxies.valueAt(i);
-                pw.print(i); pw.print(") SessionId="); pw.print(sessionId); pw.println(":");
-                proxy.dump("  ", pw);
-            }
-        }
-    }
-
-    /**
-     * Notifies the service of {@link SnapshotData snapshot data} associated with a session.
-     *
-     * @param sessionId the session's Id
-     * @param snapshotData the data
-     */
-    public void onActivitySnapshot(@NonNull InteractionSessionId sessionId,
-            @NonNull SnapshotData snapshotData) {}
-
-    /**
-     * Destroys the interaction session.
-     *
-     * @param sessionId the id of the session to destroy
-     */
-    public void onDestroyInteractionSession(@NonNull InteractionSessionId sessionId) {
-        if (VERBOSE) {
-            Log.v(TAG, "onDestroyInteractionSession(id=" + sessionId + ")");
-        }
-    }
-
-    /** @hide */
-    static final class AutofillProxy {
-
-        static final int REPORT_EVENT_ON_SUCCESS = 1;
-        static final int REPORT_EVENT_UI_SHOWN = 2;
-        static final int REPORT_EVENT_UI_DESTROYED = 3;
-
-        @IntDef(prefix = { "REPORT_EVENT_" }, value = {
-                REPORT_EVENT_ON_SUCCESS,
-                REPORT_EVENT_UI_SHOWN,
-                REPORT_EVENT_UI_DESTROYED
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        @interface ReportEvent{}
-
-
-        private final Object mLock = new Object();
-        private final IAugmentedAutofillManagerClient mClient;
-        private final int mAutofillSessionId;
-        public final InteractionSessionId sessionId;
-        public final AutofillId focusedId;
-        public final AutofillValue focusedValue;
-
-        // Objects used to log metrics
-        private final long mRequestTime;
-        private long mOnSuccessTime;
-        private long mUiFirstShownTime;
-        private long mUiFirstDestroyedTime;
-
-        @GuardedBy("mLock")
-        private SystemPopupPresentationParams mSmartSuggestion;
-
-        @GuardedBy("mLock")
-        private FillWindow mFillWindow;
-
-        private AutofillProxy(@NonNull InteractionSessionId sessionId, @NonNull IBinder client,
-                int autofillSessionId, @NonNull AutofillId focusedId,
-                @Nullable AutofillValue focusedValue, long requestTime) {
-            this.sessionId = sessionId;
-            mClient = IAugmentedAutofillManagerClient.Stub.asInterface(client);
-            mAutofillSessionId = autofillSessionId;
-            this.focusedId = focusedId;
-            this.focusedValue = focusedValue;
-            this.mRequestTime = requestTime;
-            // TODO(b/111330312): linkToDeath
-        }
-
-        @NonNull
-        public SystemPopupPresentationParams getSmartSuggestionParams() {
-            synchronized (mLock) {
-                if (mSmartSuggestion != null) {
-                    return mSmartSuggestion;
-                }
-                Rect rect;
-                try {
-                    rect = mClient.getViewCoordinates(focusedId);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Could not get coordinates for " + focusedId);
-                    return null;
-                }
-                if (rect == null) {
-                    if (DEBUG) Log.d(TAG, "getViewCoordinates(" + focusedId + ") returned null");
-                    return null;
-                }
-                mSmartSuggestion = new SystemPopupPresentationParams(this, rect);
-                return mSmartSuggestion;
-            }
-        }
-
-        public void autofill(@NonNull List<Pair<AutofillId, AutofillValue>> pairs)
-                throws RemoteException {
-            final int size = pairs.size();
-            final List<AutofillId> ids = new ArrayList<>(size);
-            final List<AutofillValue> values = new ArrayList<>(size);
-            for (int i = 0; i < size; i++) {
-                final Pair<AutofillId, AutofillValue> pair = pairs.get(i);
-                ids.add(pair.first);
-                values.add(pair.second);
-            }
-            mClient.autofill(mAutofillSessionId, ids, values);
-        }
-
-        public void setFillWindow(@NonNull FillWindow fillWindow) {
-            synchronized (mLock) {
-                mFillWindow = fillWindow;
-            }
-        }
-
-        public FillWindow getFillWindow() {
-            synchronized (mLock) {
-                return mFillWindow;
-            }
-        }
-
-        // Used for metrics.
-        public void report(@ReportEvent int event) {
-            switch (event) {
-                case REPORT_EVENT_ON_SUCCESS:
-                    if (mOnSuccessTime == 0) {
-                        mOnSuccessTime = SystemClock.elapsedRealtime();
-                        if (DEBUG) {
-                            Slog.d(TAG, "Service responsed in "
-                                    + TimeUtils.formatDuration(mOnSuccessTime - mRequestTime));
-                        }
-                    }
-                    break;
-                case REPORT_EVENT_UI_SHOWN:
-                    if (mUiFirstShownTime == 0) {
-                        mUiFirstShownTime = SystemClock.elapsedRealtime();
-                        if (DEBUG) {
-                            Slog.d(TAG, "UI shown in "
-                                    + TimeUtils.formatDuration(mUiFirstShownTime - mRequestTime));
-                        }
-                    }
-                    break;
-                case REPORT_EVENT_UI_DESTROYED:
-                    if (mUiFirstDestroyedTime == 0) {
-                        mUiFirstDestroyedTime = SystemClock.elapsedRealtime();
-                        if (DEBUG) {
-                            Slog.d(TAG, "UI destroyed in "
-                                    + TimeUtils.formatDuration(
-                                            mUiFirstDestroyedTime - mRequestTime));
-                        }
-                    }
-                    break;
-                default:
-                    Slog.w(TAG, "invalid event reported: " + event);
-            }
-            // TODO(b/111330312): log metrics as well
-        }
-
-
-        public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
-            pw.print(prefix); pw.print("afSessionId: "); pw.println(mAutofillSessionId);
-            pw.print(prefix); pw.print("focusedId: "); pw.println(focusedId);
-            if (focusedValue != null) {
-                pw.print(prefix); pw.print("focusedValue: "); pw.println(focusedValue);
-            }
-            pw.print(prefix); pw.print("client: "); pw.println(mClient);
-            final String prefix2 = prefix + "  ";
-            if (mFillWindow != null) {
-                pw.print(prefix); pw.println("window:");
-                mFillWindow.dump(prefix2, pw);
-            }
-            if (mSmartSuggestion != null) {
-                pw.print(prefix); pw.println("smartSuggestion:");
-                mSmartSuggestion.dump(prefix2, pw);
-            }
-            if (mOnSuccessTime > 0) {
-                final long responseTime = mOnSuccessTime - mRequestTime;
-                pw.print(prefix); pw.print("response time: ");
-                TimeUtils.formatDuration(responseTime, pw); pw.println();
-            }
-
-            if (mUiFirstShownTime > 0) {
-                final long uiRenderingTime = mUiFirstShownTime - mRequestTime;
-                pw.print(prefix); pw.print("UI rendering time: ");
-                TimeUtils.formatDuration(uiRenderingTime, pw); pw.println();
-            }
-
-            if (mUiFirstDestroyedTime > 0) {
-                final long uiTotalTime = mUiFirstDestroyedTime - mRequestTime;
-                pw.print(prefix); pw.print("UI life time: ");
-                TimeUtils.formatDuration(uiTotalTime, pw); pw.println();
-            }
-        }
-
-        private void destroy() {
-            synchronized (mLock) {
-                if (mFillWindow != null) {
-                    if (DEBUG) Log.d(TAG, "destroying window");
-                    mFillWindow.destroy();
-                }
-            }
-        }
-    }
-}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bd2aa64..4297efb7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -109,13 +109,13 @@
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
+import android.view.contentcapture.ContentCaptureManager;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inspector.InspectableProperty;
 import android.view.inspector.InspectableProperty.EnumMap;
 import android.view.inspector.InspectableProperty.FlagMap;
-import android.view.intelligence.ContentCaptureManager;
 import android.widget.Checkable;
 import android.widget.FrameLayout;
 import android.widget.ScrollBarDrawable;
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.aidl b/core/java/android/view/contentcapture/ContentCaptureEvent.aidl
similarity index 94%
rename from core/java/android/view/intelligence/ContentCaptureEvent.aidl
rename to core/java/android/view/contentcapture/ContentCaptureEvent.aidl
index c66a6cb..abaf9ed 100644
--- a/core/java/android/view/intelligence/ContentCaptureEvent.aidl
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.view.intelligence;
+package android.view.contentcapture;
 
 parcelable ContentCaptureEvent;
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
similarity index 91%
rename from core/java/android/view/intelligence/ContentCaptureEvent.java
rename to core/java/android/view/contentcapture/ContentCaptureEvent.java
index f636281..66fa530 100644
--- a/core/java/android/view/intelligence/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.view.intelligence;
+package android.view.contentcapture;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -42,22 +42,38 @@
 
     /**
      * Called when the activity is started.
+     *
+     * @deprecated - TODO(b/111276913): we should abstract the Activity lifecycle concepts into
+     * something related to a session and/or domain.
      */
+    @Deprecated
     public static final int TYPE_ACTIVITY_STARTED  = 1;
 
     /**
      * Called when the activity is resumed.
+     *
+     * @deprecated - TODO(b/111276913): we should abstract the Activity lifecycle concepts into
+     * something related to a session and/or domain.
      */
+    @Deprecated
     public static final int TYPE_ACTIVITY_RESUMED = 2;
 
     /**
      * Called when the activity is paused.
+     *
+     * @deprecated - TODO(b/111276913): we should abstract the Activity lifecycle concepts into
+     * something related to a session and/or domain.
      */
+    @Deprecated
     public static final int TYPE_ACTIVITY_PAUSED = 3;
 
     /**
      * Called when the activity is stopped.
+     *
+     * @deprecated - TODO(b/111276913): we should abstract the Activity lifecycle concepts into
+     * something related to a session and/or domain.
      */
+    @Deprecated
     public static final int TYPE_ACTIVITY_STOPPED  = 4;
 
     /**
@@ -163,7 +179,7 @@
      * Gets optional flags associated with the event.
      *
      * @return either {@code 0} or
-     * {@link android.view.intelligence.ContentCaptureManager#FLAG_USER_INPUT}.
+     * {@link android.view.contentcapture.ContentCaptureManager#FLAG_USER_INPUT}.
      */
     public int getFlags() {
         return mFlags;
diff --git a/core/java/android/view/intelligence/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
similarity index 95%
rename from core/java/android/view/intelligence/ContentCaptureManager.java
rename to core/java/android/view/contentcapture/ContentCaptureManager.java
index 45518d5..48831da 100644
--- a/core/java/android/view/intelligence/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -13,11 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.view.intelligence;
+package android.view.contentcapture;
 
-import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_APPEARED;
-import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
-import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_APPEARED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
 
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 
@@ -31,18 +31,18 @@
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.service.intelligence.InteractionSessionId;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewStructure;
 import android.view.autofill.AutofillId;
-import android.view.intelligence.ContentCaptureEvent.EventType;
+import android.view.contentcapture.ContentCaptureEvent.EventType;
 
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.util.Preconditions;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.UUID;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /*
@@ -58,7 +58,7 @@
 @SystemService(Context.CONTENT_CAPTURE_MANAGER_SERVICE)
 public final class ContentCaptureManager {
 
-    private static final String TAG = "ContentCaptureManager";
+    private static final String TAG = ContentCaptureManager.class.getSimpleName();
 
     // TODO(b/111276913): define a way to dynamically set them(for example, using settings?)
     private static final boolean VERBOSE = false;
@@ -113,10 +113,10 @@
     private final Context mContext;
 
     @Nullable
-    private final IIntelligenceManager mService;
+    private final IContentCaptureManager mService;
 
     @Nullable
-    private InteractionSessionId mId;
+    private String mId;
 
     private int mState = STATE_UNKNOWN;
 
@@ -137,7 +137,8 @@
     private final Handler mHandler;
 
     /** @hide */
-    public ContentCaptureManager(@NonNull Context context, @Nullable IIntelligenceManager service) {
+    public ContentCaptureManager(@NonNull Context context,
+            @Nullable IContentCaptureManager service) {
         mContext = Preconditions.checkNotNull(context, "context cannot be null");
         if (VERBOSE) {
             Log.v(TAG, "Constructor for " + context.getPackageName());
@@ -165,7 +166,7 @@
             return;
         }
         mState = STATE_WAITING_FOR_SERVER;
-        mId = new InteractionSessionId();
+        mId = UUID.randomUUID().toString();
         mApplicationToken = token;
         mComponentName = componentName;
 
diff --git a/core/java/android/view/contentcapture/IContentCaptureManager.aidl b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
new file mode 100644
index 0000000..8704dad
--- /dev/null
+++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.contentcapture;
+
+import android.content.ComponentName;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.os.IBinder;
+
+import com.android.internal.os.IResultReceiver;
+
+import java.util.List;
+
+/**
+ * {@hide}
+ */
+oneway interface IContentCaptureManager {
+    void startSession(int userId, IBinder activityToken, in ComponentName componentName,
+                      String sessionId, int flags, in IResultReceiver result);
+    void finishSession(int userId, String sessionId, in List<ContentCaptureEvent> events);
+    void sendEvents(int userId, in String sessionId, in List<ContentCaptureEvent> events);
+}
diff --git a/core/java/android/view/intelligence/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java
similarity index 99%
rename from core/java/android/view/intelligence/ViewNode.java
rename to core/java/android/view/contentcapture/ViewNode.java
index ea57461..86b89adb 100644
--- a/core/java/android/view/intelligence/ViewNode.java
+++ b/core/java/android/view/contentcapture/ViewNode.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.view.intelligence;
+package android.view.contentcapture;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 1340955..1b2d8b1 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -2520,16 +2520,6 @@
      */
     @Deprecated
     public boolean switchToLastInputMethod(IBinder imeToken) {
-        if (imeToken == null) {
-            // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission.
-            // Thus we cannot always rely on InputMethodPrivilegedOperationsRegistry unfortunately.
-            // TODO(Bug 114488811): Consider deprecating null token rule.
-            try {
-                return mService.switchToPreviousInputMethod(imeToken);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
         return InputMethodPrivilegedOperationsRegistry.get(imeToken).switchToPreviousInputMethod();
     }
 
@@ -2548,16 +2538,6 @@
      */
     @Deprecated
     public boolean switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme) {
-        if (imeToken == null) {
-            // Note: null token is allowed for callers that have WRITE_SECURE_SETTINGS permission.
-            // Thus we cannot always rely on InputMethodPrivilegedOperationsRegistry unfortunately.
-            // TODO(Bug 114488811): Consider deprecating null token rule.
-            try {
-                return mService.switchToNextInputMethod(imeToken, onlyCurrentIme);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
         return InputMethodPrivilegedOperationsRegistry.get(imeToken)
                 .switchToNextInputMethod(onlyCurrentIme);
     }
diff --git a/core/java/android/view/intelligence/IIntelligenceManager.aidl b/core/java/android/view/intelligence/IIntelligenceManager.aidl
deleted file mode 100644
index 882fb26..0000000
--- a/core/java/android/view/intelligence/IIntelligenceManager.aidl
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.intelligence;
-
-import android.content.ComponentName;
-import android.os.IBinder;
-import android.service.intelligence.InteractionSessionId;
-import android.view.intelligence.ContentCaptureEvent;
-
-import com.android.internal.os.IResultReceiver;
-
-import java.util.List;
-
-/**
- * {@hide}
- */
-// TODO(b/111276913): rename once the final name is defined
-oneway interface IIntelligenceManager {
-    /**
-      * Starts a session, sending the "remote" sessionId to the receiver.
-      */
-    void startSession(int userId, IBinder activityToken, in ComponentName componentName,
-                      in InteractionSessionId sessionId, int flags, in IResultReceiver result);
-
-    /**
-      * Finishes a session.
-      */
-    void finishSession(int userId, in InteractionSessionId sessionId,
-                       in List<ContentCaptureEvent> events);
-
-    /**
-      * Sends a batch of events
-      */
-    void sendEvents(int userId, in InteractionSessionId sessionId,
-                    in List<ContentCaptureEvent> events);
-}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index c30edd3..8b98469 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -224,6 +224,42 @@
      */
     public static final int MIXED_CONTENT_COMPATIBILITY_MODE = 2;
 
+    /** @hide */
+    @IntDef(prefix = { "FORCE_DARK_" }, value = {
+            FORCE_DARK_OFF,
+            FORCE_DARK_AUTO,
+            FORCE_DARK_ON
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ForceDarkMode {}
+
+    /**
+     * Used with {@link #setForceDarkMode}
+     *
+     * Disable force dark, irrespective of the force dark mode of the WebView parent. In this mode,
+     * WebView content will always be rendered as-is, regardless of whether native views are being
+     * automatically darkened.
+     */
+    public static final int FORCE_DARK_OFF = -1;
+
+    /**
+     * Used with {@link #setForceDarkMode}
+     *
+     * Enable force dark, dependent on the state of the WebView parent. If the WebView parent view
+     * is being automatically rendered in dark mode, then WebView content will be rendered so as to
+     * emulate a dark theme. WebViews that are not attached to the view hierarchy will not be
+     * inverted.
+     */
+    public static final int FORCE_DARK_AUTO = 0;
+
+    /**
+     * Used with {@link #setForceDarkMode}
+     *
+     * Unconditionally enable force dark. In this mode WebView content will always be rendered so
+     * as to emulate a dark theme.
+     */
+    public static final int FORCE_DARK_ON = +1;
+
     /**
      * Enables dumping the pages navigation cache to a text file. The default
      * is {@code false}.
@@ -1429,6 +1465,23 @@
 
 
     /**
+     * Set the force dark mode for this WebView.
+     */
+    public void setForceDarkMode(@ForceDarkMode int forceDarkMode) {
+        // Stub implementation to satisfy Roboelectrc shadows that don't override this yet.
+    }
+
+    /**
+     * Get the force dark mode for this WebView.
+     *
+     * @return the currently set force dark mode.
+     */
+    public @ForceDarkMode int getForceDarkMode() {
+        // Stub implementation to satisfy Roboelectrc shadows that don't override this yet.
+        return FORCE_DARK_AUTO;
+    }
+
+    /**
      * @hide
      */
     @IntDef(flag = true, prefix = { "MENU_ITEM_" }, value = {
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index c5cd1a1..365638f 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -253,8 +253,12 @@
                     final IServiceConnection sd = mContext.getServiceDispatcher(this, this, flags);
                     Intent intent = (Intent) msg.obj;
                     int appWidgetId = msg.arg1;
-                    mBindRequested = AppWidgetManager.getInstance(mContext)
-                            .bindRemoteViewsService(mContext, appWidgetId, intent, sd, flags);
+                    try {
+                        mBindRequested = AppWidgetManager.getInstance(mContext)
+                                .bindRemoteViewsService(mContext, appWidgetId, intent, sd, flags);
+                    } catch (Exception e) {
+                        Log.e(TAG, "Failed to bind remoteViewsService: " + e.getMessage());
+                    }
                     return;
                 }
                 case MSG_NOTIFY_DATA_SET_CHANGED: {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 90cf871..2a42232 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -157,6 +157,7 @@
 import android.view.animation.AnimationUtils;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
+import android.view.contentcapture.ContentCaptureManager;
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CorrectionInfo;
@@ -166,7 +167,6 @@
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
-import android.view.intelligence.ContentCaptureManager;
 import android.view.textclassifier.TextClassification;
 import android.view.textclassifier.TextClassificationContext;
 import android.view.textclassifier.TextClassificationManager;
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 1e71bd1..a5c505d 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -74,10 +74,6 @@
     boolean notifySuggestionPicked(in SuggestionSpan span, String originalString, int index);
     InputMethodSubtype getCurrentInputMethodSubtype();
     boolean setCurrentInputMethodSubtype(in InputMethodSubtype subtype);
-    // TODO(Bug 114488811): this can be removed once we deprecate special null token rule.
-    boolean switchToPreviousInputMethod(in IBinder token);
-    // TODO(Bug 114488811): this can be removed once we deprecate special null token rule.
-    boolean switchToNextInputMethod(in IBinder token, boolean onlyCurrentIme);
     void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
     // This is kept due to @UnsupportedAppUsage.
     // TODO(Bug 113914148): Consider removing this.
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index c96bacd..d5dc703 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -840,6 +840,11 @@
                     + "of length " + MIN_LOCK_PASSWORD_SIZE);
         }
 
+        if (requestedQuality < PASSWORD_QUALITY_NUMERIC) {
+            throw new IllegalArgumentException("quality must be at least NUMERIC, but was "
+                    + requestedQuality);
+        }
+
         final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
         setKeyguardStoredPasswordQuality(
                 computePasswordQuality(CREDENTIAL_TYPE_PASSWORD, password, requestedQuality),
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index d927972..7ebb2b2 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -23,8 +23,6 @@
 #include <nativehelper/JniConstants.h>
 #include "core_jni_helpers.h"
 
-#include <nativehelper/ScopedBytes.h>
-
 #include <utils/Log.h>
 #include <media/AudioSystem.h>
 #include <media/AudioTrack.h>
@@ -712,7 +710,7 @@
 
 // ----------------------------------------------------------------------------
 static jint android_media_AudioTrack_write_native_bytes(JNIEnv *env,  jobject thiz,
-        jbyteArray javaBytes, jint byteOffset, jint sizeInBytes,
+        jobject javaByteBuffer, jint byteOffset, jint sizeInBytes,
         jint javaAudioFormat, jboolean isWriteBlocking) {
     //ALOGV("android_media_AudioTrack_write_native_bytes(offset=%d, sizeInBytes=%d) called",
     //    offsetInBytes, sizeInBytes);
@@ -723,13 +721,14 @@
         return (jint)AUDIO_JAVA_INVALID_OPERATION;
     }
 
-    ScopedBytesRO bytes(env, javaBytes);
-    if (bytes.get() == NULL) {
+    const jbyte* bytes =
+            reinterpret_cast<const jbyte*>(env->GetDirectBufferAddress(javaByteBuffer));
+    if (bytes == NULL) {
         ALOGE("Error retrieving source of audio data to play, can't play");
         return (jint)AUDIO_JAVA_BAD_VALUE;
     }
 
-    jint written = writeToTrack(lpTrack, javaAudioFormat, bytes.get(), byteOffset,
+    jint written = writeToTrack(lpTrack, javaAudioFormat, bytes, byteOffset,
             sizeInBytes, isWriteBlocking == JNI_TRUE /* blocking */);
 
     return written;
@@ -1308,7 +1307,7 @@
     {"native_release",       "()V",      (void *)android_media_AudioTrack_release},
     {"native_write_byte",    "([BIIIZ)I",(void *)android_media_AudioTrack_writeArray<jbyteArray>},
     {"native_write_native_bytes",
-                             "(Ljava/lang/Object;IIIZ)I",
+                             "(Ljava/nio/ByteBuffer;IIIZ)I",
                                          (void *)android_media_AudioTrack_write_native_bytes},
     {"native_write_short",   "([SIIIZ)I",(void *)android_media_AudioTrack_writeArray<jshortArray>},
     {"native_write_float",   "([FIIIZ)I",(void *)android_media_AudioTrack_writeArray<jfloatArray>},
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index b1a9866..06625b3 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -32,15 +32,16 @@
     android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str());
 }
 
-void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jboolean devOptIn,
+void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jstring devOptIn,
                          jobject rulesFd, jlong rulesOffset, jlong rulesLength) {
     ScopedUtfChars pathChars(env, path);
     ScopedUtfChars appNameChars(env, appName);
+    ScopedUtfChars devOptInChars(env, devOptIn);
 
     int rulesFd_native = jniGetFDFromFileDescriptor(env, rulesFd);
 
     android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), appNameChars.c_str(),
-            devOptIn, rulesFd_native, rulesOffset, rulesLength);
+            devOptInChars.c_str(), rulesFd_native, rulesOffset, rulesLength);
 }
 
 void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) {
@@ -67,7 +68,7 @@
 const JNINativeMethod g_methods[] = {
     { "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
     { "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
-    { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;ZLjava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
+    { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
     { "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
     { "setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayers_native) },
     { "setDebugLayersGLES", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayersGLES_native) },
diff --git a/core/proto/android/app/job/enums.proto b/core/proto/android/app/job/enums.proto
index 2290b2f..bba8328 100644
--- a/core/proto/android/app/job/enums.proto
+++ b/core/proto/android/app/job/enums.proto
@@ -30,4 +30,5 @@
     STOP_REASON_PREEMPT = 2;
     STOP_REASON_TIMEOUT = 3;
     STOP_REASON_DEVICE_IDLE = 4;
+    STOP_REASON_DEVICE_THERMAL = 5;
 }
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 8e4eb00..fd64c65 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -73,5 +73,8 @@
 
     // OPEN: Settings > Privacy
     TOP_LEVEL_PRIVACY = 1587;
+
+    // OPEN: Settings > Developer options > Disable > Info dialog
+    DIALOG_DISABLE_DEVELOPMENT_OPTIONS = 1591;
 }
 
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 0b9e347..a5350c9 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -34,6 +34,7 @@
 import "frameworks/base/core/proto/android/server/fingerprint.proto";
 import "frameworks/base/core/proto/android/server/jobscheduler.proto";
 import "frameworks/base/core/proto/android/server/powermanagerservice.proto";
+import "frameworks/base/core/proto/android/server/rolemanagerservice.proto";
 import "frameworks/base/core/proto/android/server/windowmanagerservice.proto";
 import "frameworks/base/core/proto/android/service/appwidget.proto";
 import "frameworks/base/core/proto/android/service/battery.proto";
@@ -308,6 +309,11 @@
         (section).userdebug_and_eng_only = true
     ];
 
+    optional com.android.server.role.RoleManagerServiceDumpProto role = 3024 [
+        (section).type = SECTION_DUMPSYS,
+        (section).args = "role --proto"
+    ];
+
     // Reserved for OEMs.
     extensions 50000 to 100000;
 }
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 4c1fc5c..11bd43b 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -109,7 +109,15 @@
     }
     optional Autofill autofill = 140;
 
-    optional SettingProto backup_agent_timeout_parameters = 18;
+    reserved 18; // Used to be backup_agent_timeout_parameters
+
+    message Backup {
+        option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+        optional SettingProto backup_agent_timeout_parameters = 1;
+        optional SettingProto backup_multi_user_enabled = 2;
+    }
+    optional Backup backup = 146;
 
     message Battery {
         option (android.msg_privacy).dest = DEST_EXPLICIT;
@@ -222,6 +230,13 @@
     }
     optional Connectivity connectivity = 32;
 
+    message ContentCapture {
+      option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+      optional SettingProto service_explicitly_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    }
+    optional ContentCapture content_capture = 145;
+
     optional SettingProto contact_metadata_sync_enabled = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto contacts_database_wal_enabled = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
@@ -410,16 +425,20 @@
         // Ordered GPU debug layer list for Vulkan
         // i.e. <layer1>:<layer2>:...:<layerN>
         optional SettingProto debug_layers = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
-        // App will load ANGLE instead of native GLES drivers.
-        optional SettingProto angle_enabled_app = 3;
+        // ANGLE - Force all PKGs to use ANGLE, regardless of any other settings
+        optional SettingProto angle_gl_driver_all_angle = 3;
+        // ANGLE - List of PKGs that specify an OpenGL driver
+        optional SettingProto angle_gl_driver_selection_pkgs = 4;
+        // ANGLE - Corresponding OpenGL driver selection for the PKG
+        optional SettingProto angle_gl_driver_selection_values = 5;
         // App that can provide layer libraries.
-        optional SettingProto debug_layer_app = 4;
+        optional SettingProto debug_layer_app = 6;
         // Ordered GPU debug layer list for GLES
         // i.e. <layer1>:<layer2>:...:<layerN>
-        optional SettingProto debug_layers_gles = 5;
+        optional SettingProto debug_layers_gles = 7;
         // App opt in to load updated graphics driver instead of
         // native graphcis driver through developer options.
-        optional SettingProto updated_gfx_driver_dev_opt_in_app = 6;
+        optional SettingProto updated_gfx_driver_dev_opt_in_app = 8;
     }
     optional Gpu gpu = 59;
 
@@ -628,6 +647,9 @@
         // separated by commas.
         optional SettingProto snooze_options = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto smart_replies_in_notifications_flags = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        // Configuration options for smart replies and smart actions in notifications. This is
+        // encoded as a key=value list separated by commas.
+        optional SettingProto smart_suggestions_in_notifications_flags = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
     optional Notification notification = 82;
 
@@ -761,13 +783,6 @@
     }
     optional SmartSelection smart_selection = 108;
 
-    message SmartSuggestions {
-      option (android.msg_privacy).dest = DEST_EXPLICIT;
-
-      optional SettingProto service_explicitly_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    }
-    optional SmartSuggestions smart_suggestions = 145;
-
     message Sms {
         option (android.msg_privacy).dest = DEST_EXPLICIT;
 
@@ -1000,5 +1015,5 @@
 
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 146;
+    // Next tag = 147;
 }
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 231caab..c2bc7bf 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -41,6 +41,7 @@
     optional int64 last_heartbeat_time_millis = 16;
     optional int64 next_heartbeat_time_millis = 17;
     optional bool in_parole = 18;
+    optional bool in_thermal = 19;
 
     repeated int32 started_users = 2;
 
diff --git a/core/proto/android/server/rolemanagerservice.proto b/core/proto/android/server/rolemanagerservice.proto
new file mode 100644
index 0000000..3453a66
--- /dev/null
+++ b/core/proto/android/server/rolemanagerservice.proto
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package com.android.server.role;
+
+option java_multiple_files = true;
+
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+message RoleManagerServiceDumpProto {
+  option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+  // List of per-user states for all users.
+  repeated RoleUserStateProto user_states = 1;
+}
+
+message RoleUserStateProto {
+  option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+  // The user id of this state.
+  optional int32 user_id = 1;
+
+  // The version of this state.
+  optional int32 version = 2;
+
+  // The hash of packages for this state.
+  optional string packages_hash = 3;
+
+  // The set of roles in this state.
+  repeated RoleProto roles = 4;
+}
+
+message RoleProto {
+  option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+  // The name of this role, e.g. "android.app.role.DIALER".
+  optional string name = 1;
+
+  // The package names of the holders of this role.
+  repeated string holders = 2;
+}
diff --git a/core/proto/android/stats/docsui/docsui_enums.proto b/core/proto/android/stats/docsui/docsui_enums.proto
new file mode 100644
index 0000000..6cb606a
--- /dev/null
+++ b/core/proto/android/stats/docsui/docsui_enums.proto
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+package android.stats.docsui;
+option java_multiple_files = true;
+
+enum LaunchAction {
+    UNKNOWN = 0;
+    OPEN = 1;
+    CREATE = 2;
+    GET_CONTENT = 3;
+    OPEN_TREE = 4;
+    PICK_COPY_DEST = 5;
+    BROWSE = 6;
+    OTHER = 7;
+}
+
+enum MimeType {
+    MIME_UNKNOWN = 0;
+    MIME_NONE = 1;
+    MIME_ANY = 2;
+    MIME_AUDIO = 3;
+    MIME_IMAGE = 4;
+    MIME_MESSAGE = 5;
+    MIME_MULTIPART = 6;
+    MIME_TEXT = 7;
+    MIME_VIDEO = 8;
+    MIME_OTHER = 9;
+}
+
+enum Root {
+    ROOT_UNKNOWN = 0;
+    ROOT_NONE = 1;
+    ROOT_OTHER_DOCS_PROVIDER = 2;
+    ROOT_AUDIO = 3;
+    ROOT_DEVICE_STORAGE = 4;
+    ROOT_DOWNLOADS = 5;
+    ROOT_HOME = 6;
+    ROOT_IMAGES = 7;
+    ROOT_RECENTS = 8;
+    ROOT_VIDEOS = 9;
+    ROOT_MTP = 10;
+    ROOT_THIRD_PARTY_APP = 11;
+}
+
+enum ContextScope {
+    SCOPE_UNKNOWN = 0;
+    SCOPE_FILES = 1;
+    SCOPE_PICKER = 2;
+}
+
+enum Provider {
+    PROVIDER_UNKNOWN = 0;
+    PROVIDER_SYSTEM = 1;
+    PROVIDER_EXTERNAL = 2;
+}
+
+enum FileOperation {
+    OP_UNKNOWN = 0;
+    OP_OTHER = 1;
+    OP_COPY = 2;
+    OP_COPY_INTRA_PROVIDER = 3;
+    OP_COPY_SYSTEM_PROVIDER = 4;
+    OP_COPY_EXTERNAL_PROVIDER = 5;
+    OP_MOVE = 6;
+    OP_MOVE_INTRA_PROVIDER = 7;
+    OP_MOVE_SYSTEM_PROVIDER = 8;
+    OP_MOVE_EXTERNAL_PROVIDER = 9;
+    OP_DELETE = 10;
+    OP_RENAME = 11;
+    OP_CREATE_DIR = 12;
+    OP_OTHER_ERROR = 13;
+    OP_DELETE_ERROR = 14;
+    OP_MOVE_ERROR = 15;
+    OP_COPY_ERROR = 16;
+    OP_RENAME_ERROR = 17;
+    OP_CREATE_DIR_ERROR = 18;
+    OP_COMPRESS_INTRA_PROVIDER = 19;
+    OP_COMPRESS_SYSTEM_PROVIDER = 20;
+    OP_COMPRESS_EXTERNAL_PROVIDER = 21;
+    OP_EXTRACT_INTRA_PROVIDER = 22;
+    OP_EXTRACT_SYSTEM_PROVIDER = 23;
+    OP_EXTRACT_EXTERNAL_PROVIDER = 24;
+    OP_COMPRESS_ERROR = 25;
+    OP_EXTRACT_ERROR = 26;
+}
+
+enum SubFileOperation {
+    SUB_OP_UNKNOWN = 0;
+    SUB_OP_QUERY_DOC = 1;
+    SUB_OP_QUERY_CHILD = 2;
+    SUB_OP_OPEN_FILE = 3;
+    SUB_OP_READ_FILE = 4;
+    SUB_OP_CREATE_DOC = 5;
+    SUB_OP_WRITE_FILE = 6;
+    SUB_OP_DELETE_DOC = 7;
+    SUB_OP_OBTAIN_STREAM_TYPE = 8;
+    SUB_OP_QUICK_MOVE = 9;
+    SUB_OP_QUICK_COPY = 10;
+}
+
+enum CopyMoveOpMode {
+    MODE_UNKNOWN = 0;
+    MODE_PROVIDER = 1;
+    MODE_CONVERTED = 2;
+    MODE_CONVENTIONAL = 3;
+}
+
+enum Authority {
+    AUTH_UNKNOWN = 0;
+    AUTH_OTHER = 1;
+    AUTH_MEDIA = 2;
+    AUTH_STORAGE_INTERNAL = 3;
+    AUTH_STORAGE_EXTERNAL = 4;
+    AUTH_DOWNLOADS = 5;
+    AUTH_MTP = 6;
+}
+
+enum UserAction {
+    ACTION_UNKNOWN = 0;
+    ACTION_OTHER = 1;
+    ACTION_GRID = 2;
+    ACTION_LIST = 3;
+    ACTION_SORT_NAME = 4;
+    ACTION_SORT_DATE = 5;
+    ACTION_SORT_SIZE = 6;
+    ACTION_SORT_TYPE = 7;
+    ACTION_SEARCH = 8;
+    ACTION_SHOW_SIZE = 9;
+    ACTION_HIDE_SIZE = 10;
+    ACTION_SETTINGS = 11;
+    ACTION_COPY_TO = 12;
+    ACTION_MOVE_TO = 13;
+    ACTION_DELETE = 14;
+    ACTION_RENAME = 15;
+    ACTION_CREATE_DIR = 16;
+    ACTION_SELECT_ALL = 17;
+    ACTION_SHARE = 18;
+    ACTION_OPEN = 19;
+    ACTION_SHOW_ADVANCED = 20;
+    ACTION_HIDE_ADVANCED = 21;
+    ACTION_NEW_WINDOW = 22;
+    ACTION_PASTE_CLIPBOARD = 23;
+    ACTION_COPY_CLIPBOARD = 24;
+    ACTION_DRAG_N_DROP = 25;
+    ACTION_DRAG_N_DROP_MULTI_WINDOW = 26;
+    ACTION_CUT_CLIPBOARD = 27;
+    ACTION_COMPRESS = 28;
+    ACTION_EXTRACT_TO = 29;
+    ACTION_VIEW_IN_APPLICATION = 30;
+    ACTION_INSPECTOR = 31;
+}
+
+enum InvalidScopedAccess {
+    SCOPED_DIR_ACCESS_UNKNOWN = 0;
+    SCOPED_DIR_ACCESS_INVALID_ARGUMENTS = 1;
+    SCOPED_DIR_ACCESS_INVALID_DIRECTORY = 2;
+    SCOPED_DIR_ACCESS_ERROR = 3;
+    SCOPED_DIR_ACCESS_DEPRECATED = 4;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3018614..1dd42b8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1595,7 +1595,7 @@
          @hide This should only be used by ManagedProvisioning app.
     -->
     <permission android:name="android.permission.NETWORK_MANAGED_PROVISIONING"
-        android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature" />
 
     <!-- #SystemApi @hide Allows applications to access information about LoWPAN interfaces.
          <p>Not for use by third-party applications. -->
@@ -3047,12 +3047,20 @@
     <permission android:name="android.permission.BIND_TEXTCLASSIFIER_SERVICE"
                 android:protectionLevel="signature" />
 
-    <!-- Must be required by a android.service.intelligence.SmartSuggestionsService,
+    <!-- Must be required by a android.service.contentcapture.ContentCaptureService,
          to ensure that only the system can bind to it.
          @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
          <p>Protection level: signature
     -->
-    <permission android:name="android.permission.BIND_SMART_SUGGESTIONS_SERVICE"
+    <permission android:name="android.permission.BIND_CONTENT_CAPTURE_SERVICE"
+                android:protectionLevel="signature" />
+
+    <!-- Must be required by a android.service.autofill.augmented.AugmentedAutofillService,
+         to ensure that only the system can bind to it.
+         @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+         <p>Protection level: signature
+    -->
+    <permission android:name="android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE"
                 android:protectionLevel="signature" />
 
     <!-- Must be required by hotword enrollment application,
@@ -4177,9 +4185,9 @@
     <permission android:name="android.permission.MANAGE_AUTO_FILL"
         android:protectionLevel="signature" />
 
-    <!-- @SystemApi Allows an application to manage the smart suggestions service.
+    <!-- @SystemApi Allows an application to manage the content capture service.
          @hide  <p>Not for use by third-party applications.</p> -->
-    <permission android:name="android.permission.MANAGE_SMART_SUGGESTIONS"
+    <permission android:name="android.permission.MANAGE_CONTENT_CAPTURE"
         android:protectionLevel="signature" />
 
     <!-- Allows an app to set the theme overlay in /vendor/overlay
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 499278c..62ec5c4 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3350,13 +3350,21 @@
     -->
     <string name="config_defaultTextClassifierPackage" translatable="false"></string>
 
-    <!-- The package name for the system's smart suggestion service.
+    <!-- The package name for the system's content capture service.
          This service must be trusted, as it can be activated without explicit consent of the user.
-         If no service with the specified name exists on the device, content capture and
-         smart suggestions will be disabled.
-         Example: "com.android.intelligence/.SmartSuggestionsService"
+         If no service with the specified name exists on the device, content capture will be
+         disabled.
+         Example: "com.android.contentcapture/.ContentcaptureService"
     -->
-    <string name="config_defaultSmartSuggestionsService" translatable="false"></string>
+    <string name="config_defaultContentCaptureService" translatable="false"></string>
+
+    <!-- The package name for the system's augmented autofill service.
+         This service must be trusted, as it can be activated without explicit consent of the user.
+         If no service with the specified name exists on the device, augmented autofill wil be
+         disabled.
+         Example: "com.android.augmentedautofill/.AugmentedAutofillService"
+    -->
+    <string name="config_defaultAugmentedAutofillService" translatable="false"></string>
 
     <!-- Whether the device uses the default focus highlight when focus state isn't specified. -->
     <bool name="config_useDefaultFocusHighlight">true</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6854a84e..82a679e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3265,7 +3265,8 @@
   <java-symbol type="string" name="notification_channel_do_not_disturb" />
   <java-symbol type="string" name="config_defaultAutofillService" />
   <java-symbol type="string" name="config_defaultTextClassifierPackage" />
-  <java-symbol type="string" name="config_defaultSmartSuggestionsService" />
+  <java-symbol type="string" name="config_defaultContentCaptureService" />
+  <java-symbol type="string" name="config_defaultAugmentedAutofillService" />
 
   <java-symbol type="string" name="notification_channel_foreground_service" />
   <java-symbol type="string" name="foreground_service_app_in_background" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index ed9c3d5..49a7555 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -183,6 +183,7 @@
                     Settings.Global.CONNECTIVITY_METRICS_BUFFER_SIZE,
                     Settings.Global.CONNECTIVITY_SAMPLING_INTERVAL_IN_SECONDS,
                     Settings.Global.CONTACT_METADATA_SYNC_ENABLED,
+                    Settings.Global.CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED,
                     Settings.Global.CONVERSATION_ACTIONS_UPDATE_CONTENT_URL,
                     Settings.Global.CONVERSATION_ACTIONS_UPDATE_METADATA_URL,
                     Settings.Global.CONTACTS_DATABASE_WAL_ENABLED,
@@ -247,6 +248,7 @@
                     Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
                     Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
                     Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
+                    Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS,
                     Settings.Global.ENHANCED_4G_MODE_ENABLED,
                     Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
                     Settings.Global.ERROR_LOGCAT_PREFIX,
@@ -415,7 +417,6 @@
                     Settings.Global.SHOW_TEMPERATURE_WARNING,
                     Settings.Global.SMART_SELECTION_UPDATE_CONTENT_URL,
                     Settings.Global.SMART_SELECTION_UPDATE_METADATA_URL,
-                    Settings.Global.SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED,
                     Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED,
                     Settings.Global.SMS_OUTGOING_CHECK_INTERVAL_MS,
                     Settings.Global.SMS_OUTGOING_CHECK_MAX_COUNT,
@@ -469,7 +470,9 @@
                     Settings.Global.GPU_DEBUG_APP,
                     Settings.Global.GPU_DEBUG_LAYERS,
                     Settings.Global.GPU_DEBUG_LAYERS_GLES,
-                    Settings.Global.ANGLE_ENABLED_APP,
+                    Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE,
+                    Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS,
+                    Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES,
                     Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP,
                     Settings.Global.GPU_DEBUG_LAYER_APP,
                     Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
@@ -538,7 +541,8 @@
                     Settings.Global.OVERRIDE_SETTINGS_PROVIDER_RESTORE_ANY_VERSION,
                     Settings.Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED,
                     Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS,
-                    Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS);
+                    Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS,
+                    Settings.Global.BACKUP_MULTI_USER_ENABLED);
     private static final Set<String> BACKUP_BLACKLISTED_SECURE_SETTINGS =
              newHashSet(
                  Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
diff --git a/core/tests/coretests/src/android/provider/SettingsProviderTest.java b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
index 108585d..04e8802 100644
--- a/core/tests/coretests/src/android/provider/SettingsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
@@ -16,6 +16,10 @@
 
 package android.provider;
 
+import static org.hamcrest.Matchers.aMapWithSize;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.junit.Assert.assertThat;
+
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -26,6 +30,7 @@
 import android.content.pm.UserInfo;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.test.AndroidTestCase;
@@ -33,10 +38,19 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.test.suitebuilder.annotation.Suppress;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /** Unit test for SettingsProvider. */
 public class SettingsProviderTest extends AndroidTestCase {
+    /**
+     * TODO(b/113100523): Move this to DeviceConfig.java when it is added, and expose it as a System
+     *     API.
+     */
+    private static final Uri CONFIG_CONTENT_URI =
+            Uri.parse("content://" + Settings.AUTHORITY + "/config");
+
     @MediumTest
     public void testNameValueCache() {
         ContentResolver r = getContext().getContentResolver();
@@ -379,4 +393,109 @@
 
         assertTrue(ssaid.equals(ssaid2));
     }
+
+    @MediumTest
+    public void testCall_putAndGetConfig() {
+        ContentResolver r = getContext().getContentResolver();
+        String name = "key1";
+        String value = "value1";
+        String newValue = "value2";
+        Bundle args = new Bundle();
+        args.putString(Settings.NameValueTable.VALUE, value);
+
+        try {
+            // value is empty
+            Bundle results =
+                    r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
+            assertNull(results.get(Settings.NameValueTable.VALUE));
+
+            // save value
+            results = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, name, args);
+            assertNull(results);
+
+            // value is no longer empty
+            results = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
+            assertEquals(value, results.get(Settings.NameValueTable.VALUE));
+
+            // save new value
+            args.putString(Settings.NameValueTable.VALUE, newValue);
+            r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, name, args);
+
+            // new value is returned
+            results = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
+            assertEquals(newValue, results.get(Settings.NameValueTable.VALUE));
+        } finally {
+            // clean up
+            r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, name, null);
+        }
+    }
+
+    @MediumTest
+    public void testCall_deleteConfig() {
+        ContentResolver r = getContext().getContentResolver();
+        String name = "key1";
+        String value = "value1";
+        Bundle args = new Bundle();
+        args.putString(Settings.NameValueTable.VALUE, value);
+
+        try {
+            // save value
+            r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, name, args);
+
+            // get value
+            Bundle results =
+                    r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
+            assertEquals(value, results.get(Settings.NameValueTable.VALUE));
+
+            // delete value
+            results = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, name, null);
+
+            // value is empty now
+            results = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
+            assertNull(results.get(Settings.NameValueTable.VALUE));
+        } finally {
+            // clean up
+            r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, name, null);
+        }
+    }
+
+    @MediumTest
+    public void testCall_listConfig() {
+        ContentResolver r = getContext().getContentResolver();
+        String prefix = "foo";
+        String newPrefix = "bar";
+        String name = prefix + "/" + "key1";
+        String newName = newPrefix + "/" + "key1";
+        String value = "value1";
+        String newValue = "value2";
+        Bundle args = new Bundle();
+        args.putString(Settings.NameValueTable.VALUE, value);
+
+        try {
+            // save both values
+            r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, name, args);
+            args.putString(Settings.NameValueTable.VALUE, newValue);
+            r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, newName, args);
+
+            // list all values
+            Bundle result = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_LIST_CONFIG,
+                    null, null);
+            Map<String, String> keyValueMap =
+                    (HashMap) result.getSerializable(Settings.NameValueTable.VALUE);
+            assertThat(keyValueMap.size(), greaterThanOrEqualTo(2));
+            assertEquals(value, keyValueMap.get(name));
+            assertEquals(newValue, keyValueMap.get(newName));
+
+            // list values for prefix
+            args.putString(Settings.CALL_METHOD_PREFIX_KEY, prefix);
+            result = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_LIST_CONFIG, null, args);
+            keyValueMap = (HashMap) result.getSerializable(Settings.NameValueTable.VALUE);
+            assertThat(keyValueMap, aMapWithSize(1));
+            assertEquals(value, keyValueMap.get(name));
+        } finally {
+            // clean up
+            r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, name, null);
+            r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, newName, null);
+        }
+    }
 }
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index ed7d5e5..d22eaf3 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -178,6 +178,7 @@
         "renderthread/CanvasContext.cpp",
         "renderthread/DrawFrameTask.cpp",
         "renderthread/EglManager.cpp",
+        "renderthread/ReliableSurface.cpp",
         "renderthread/VulkanManager.cpp",
         "renderthread/RenderProxy.cpp",
         "renderthread/RenderTask.cpp",
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index c63e449..0b847af 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -912,18 +912,6 @@
     fDL->drawAnnotation(rect, key, val);
 }
 
-void RecordingCanvas::onDrawText(const void* text, size_t bytes, SkScalar x, SkScalar y,
-                                 const SkPaint& paint) {
-    fDL->drawText(text, bytes, x, y, paint);
-}
-void RecordingCanvas::onDrawPosText(const void* text, size_t bytes, const SkPoint pos[],
-                                    const SkPaint& paint) {
-    fDL->drawPosText(text, bytes, pos, paint);
-}
-void RecordingCanvas::onDrawPosTextH(const void* text, size_t bytes, const SkScalar xs[],
-                                     SkScalar y, const SkPaint& paint) {
-    fDL->drawPosTextH(text, bytes, xs, y, paint);
-}
 void RecordingCanvas::onDrawTextRSXform(const void* text, size_t bytes, const SkRSXform xform[],
                                         const SkRect* cull, const SkPaint& paint) {
     fDL->drawTextRSXform(text, bytes, xform, cull, paint);
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 08cfc62..35cf707 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -170,10 +170,6 @@
     void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
     void onDrawAnnotation(const SkRect&, const char[], SkData*) override;
 
-    void onDrawText(const void*, size_t, SkScalar x, SkScalar y, const SkPaint&) override;
-    void onDrawPosText(const void*, size_t, const SkPoint[], const SkPaint&) override;
-    void onDrawPosTextH(const void*, size_t, const SkScalar[], SkScalar, const SkPaint&) override;
-
     void onDrawTextRSXform(const void*, size_t, const SkRSXform[], const SkRect*,
                            const SkPaint&) override;
     void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override;
diff --git a/libs/hwui/pipeline/skia/DumpOpsCanvas.h b/libs/hwui/pipeline/skia/DumpOpsCanvas.h
index 2062194..2b5d580 100644
--- a/libs/hwui/pipeline/skia/DumpOpsCanvas.h
+++ b/libs/hwui/pipeline/skia/DumpOpsCanvas.h
@@ -82,18 +82,6 @@
         mOutput << mIdent << "drawDRRect" << std::endl;
     }
 
-    void onDrawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&) override {
-        mOutput << mIdent << "drawText" << std::endl;
-    }
-
-    void onDrawPosText(const void*, size_t, const SkPoint[], const SkPaint&) override {
-        mOutput << mIdent << "drawPosText" << std::endl;
-    }
-
-    void onDrawPosTextH(const void*, size_t, const SkScalar[], SkScalar, const SkPaint&) override {
-        mOutput << mIdent << "drawPosTextH" << std::endl;
-    }
-
     void onDrawTextRSXform(const void*, size_t, const SkRSXform[], const SkRect*,
                            const SkPaint&) override {
         mOutput << mIdent << "drawTextRSXform" << std::endl;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 142bca9..07979a2 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -155,7 +155,7 @@
     }
 }
 
-bool SkiaOpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior,
+bool SkiaOpenGLPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBehavior,
                                     ColorMode colorMode) {
     if (mEglSurface != EGL_NO_SURFACE) {
         mEglManager.destroySurface(mEglSurface);
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index 4ab3541..47991069 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -42,7 +42,7 @@
     bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
                      FrameInfo* currentFrameInfo, bool* requireSwap) override;
     DeferredLayerUpdater* createTextureLayer() override;
-    bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior,
+    bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior,
                     renderthread::ColorMode colorMode) override;
     void onStop() override;
     bool isSurfaceReady() override;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 3607b23..437b5dc 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -115,7 +115,7 @@
 
 void SkiaVulkanPipeline::onStop() {}
 
-bool SkiaVulkanPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior,
+bool SkiaVulkanPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBehavior,
                                     ColorMode colorMode) {
     if (mVkSurface) {
         mVkManager.destroySurface(mVkSurface);
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index 14c0d69..02874c7 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -38,7 +38,7 @@
     bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
                      FrameInfo* currentFrameInfo, bool* requireSwap) override;
     DeferredLayerUpdater* createTextureLayer() override;
-    bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior,
+    bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior,
                     renderthread::ColorMode colorMode) override;
     void onStop() override;
     bool isSurfaceReady() override;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 6869972..4e4262c 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -142,7 +142,12 @@
 void CanvasContext::setSurface(sp<Surface>&& surface) {
     ATRACE_CALL();
 
-    mNativeSurface = std::move(surface);
+    if (surface) {
+        mNativeSurface = new ReliableSurface{std::move(surface)};
+        mNativeSurface->setDequeueTimeout(500_ms);
+    } else {
+        mNativeSurface = nullptr;
+    }
 
     ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::SRGB;
     bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode);
@@ -285,10 +290,11 @@
 
     info.damageAccumulator = &mDamageAccumulator;
     info.layerUpdateQueue = &mLayerUpdateQueue;
+    info.out.canDrawThisFrame = true;
 
     mAnimationContext->startFrame(info.mode);
     mRenderPipeline->onPrepareTree();
-    for (const sp<RenderNode>& node : mRenderNodes) {
+    for (const sp<RenderNode> &node : mRenderNodes) {
         // Only the primary target node will be drawn full - all other nodes would get drawn in
         // real time mode. In case of a window, the primary node is the window content and the other
         // node(s) are non client / filler nodes.
@@ -304,7 +310,7 @@
 
     mIsDirty = true;
 
-    if (CC_UNLIKELY(!mNativeSurface.get())) {
+    if (CC_UNLIKELY(!hasSurface())) {
         mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
         info.out.canDrawThisFrame = false;
         return;
@@ -312,7 +318,7 @@
 
     if (CC_LIKELY(mSwapHistory.size() && !Properties::forceDrawFrame)) {
         nsecs_t latestVsync = mRenderThread.timeLord().latestVsync();
-        SwapHistory& lastSwap = mSwapHistory.back();
+        SwapHistory &lastSwap = mSwapHistory.back();
         nsecs_t vsyncDelta = std::abs(lastSwap.vsyncTime - latestVsync);
         // The slight fudge-factor is to deal with cases where
         // the vsync was estimated due to being slow handling the signal.
@@ -333,7 +339,19 @@
         info.out.canDrawThisFrame = false;
     }
 
-    if (!info.out.canDrawThisFrame) {
+    if (info.out.canDrawThisFrame) {
+        int err = mNativeSurface->reserveNext();
+        if (err != OK) {
+            mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
+            info.out.canDrawThisFrame = false;
+            ALOGW("reserveNext failed, error = %d (%s)", err, strerror(-err));
+            if (err != TIMED_OUT) {
+                // A timed out surface can still recover, but assume others are permanently dead.
+                setSurface(nullptr);
+                return;
+            }
+        }
+    } else {
         mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
     }
 
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 70be4a6..9e7abf4 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -25,6 +25,7 @@
 #include "IRenderPipeline.h"
 #include "LayerUpdateQueue.h"
 #include "RenderNode.h"
+#include "ReliableSurface.h"
 #include "renderthread/RenderTask.h"
 #include "renderthread/RenderThread.h"
 #include "thread/Task.h"
@@ -219,7 +220,7 @@
     EGLint mLastFrameHeight = 0;
 
     RenderThread& mRenderThread;
-    sp<Surface> mNativeSurface;
+    sp<ReliableSurface> mNativeSurface;
     // stopped indicates the CanvasContext will reject actual redraw operations,
     // and defer repaint until it is un-stopped
     bool mStopped = false;
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 65ced6a..8230dfd 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -31,6 +31,8 @@
 
 #include <string>
 #include <vector>
+#include <system/window.h>
+#include <gui/Surface.h>
 
 #define GLES_VERSION 2
 
@@ -106,7 +108,7 @@
     LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE,
                         "Failed to initialize display %p! err=%s", mEglDisplay, eglErrorString());
 
-    ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor);
+    ALOGV("Initialized EGL, version %d.%d", (int)major, (int)minor);
 
     initExtensions();
 
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 4972554..42e17b273 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -28,9 +28,9 @@
 
 class GrContext;
 
-namespace android {
+struct ANativeWindow;
 
-class Surface;
+namespace android {
 
 namespace uirenderer {
 
@@ -67,7 +67,7 @@
     virtual bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
                              FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
     virtual DeferredLayerUpdater* createTextureLayer() = 0;
-    virtual bool setSurface(Surface* window, SwapBehavior swapBehavior, ColorMode colorMode) = 0;
+    virtual bool setSurface(ANativeWindow* window, SwapBehavior swapBehavior, ColorMode colorMode) = 0;
     virtual void onStop() = 0;
     virtual bool isSurfaceReady() = 0;
     virtual bool isContextReady() = 0;
diff --git a/libs/hwui/renderthread/ReliableSurface.cpp b/libs/hwui/renderthread/ReliableSurface.cpp
new file mode 100644
index 0000000..6f2b9df
--- /dev/null
+++ b/libs/hwui/renderthread/ReliableSurface.cpp
@@ -0,0 +1,318 @@
+/*
+ * 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.
+ */
+
+#include "ReliableSurface.h"
+
+#include <private/android/AHardwareBufferHelpers.h>
+
+namespace android::uirenderer::renderthread {
+
+// TODO: Re-enable after addressing more of the TODO's
+// With this disabled we won't have a good up-front signal that the surface is no longer valid,
+// however we can at least handle that reactively post-draw. There's just not a good mechanism
+// to propagate this error back to the caller
+constexpr bool DISABLE_BUFFER_PREFETCH = true;
+
+// TODO: Make surface less protected
+// This exists because perform is a varargs, and ANativeWindow has no va_list perform.
+// So wrapping/chaining that is hard. Telling the compiler to ignore protected is easy, so we do
+// that instead
+struct SurfaceExposer : Surface {
+    // Make warnings happy
+    SurfaceExposer() = delete;
+
+    using Surface::setBufferCount;
+    using Surface::setSwapInterval;
+    using Surface::dequeueBuffer;
+    using Surface::queueBuffer;
+    using Surface::cancelBuffer;
+    using Surface::lockBuffer_DEPRECATED;
+    using Surface::perform;
+};
+
+#define callProtected(surface, func, ...) ((*surface).*&SurfaceExposer::func)(__VA_ARGS__)
+
+ReliableSurface::ReliableSurface(sp<Surface>&& surface) : mSurface(std::move(surface)) {
+    LOG_ALWAYS_FATAL_IF(!mSurface, "Error, unable to wrap a nullptr");
+
+    ANativeWindow::setSwapInterval = hook_setSwapInterval;
+    ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
+    ANativeWindow::cancelBuffer = hook_cancelBuffer;
+    ANativeWindow::queueBuffer = hook_queueBuffer;
+    ANativeWindow::query = hook_query;
+    ANativeWindow::perform = hook_perform;
+
+    ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
+    ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED;
+    ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED;
+    ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED;
+}
+
+ReliableSurface::~ReliableSurface() {
+    clearReservedBuffer();
+}
+
+void ReliableSurface::perform(int operation, va_list args) {
+    std::lock_guard _lock{mMutex};
+
+    switch (operation) {
+        case NATIVE_WINDOW_SET_USAGE:
+            mUsage = va_arg(args, uint32_t);
+            break;
+        case NATIVE_WINDOW_SET_USAGE64:
+            mUsage = va_arg(args, uint64_t);
+            break;
+        case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
+            /* width */ va_arg(args, uint32_t);
+            /* height */ va_arg(args, uint32_t);
+            mFormat = va_arg(args, PixelFormat);
+            break;
+        case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
+            mFormat = va_arg(args, PixelFormat);
+            break;
+    }
+}
+
+int ReliableSurface::reserveNext() {
+    {
+        std::lock_guard _lock{mMutex};
+        if (mReservedBuffer) {
+            ALOGW("reserveNext called but there was already a buffer reserved?");
+            return OK;
+        }
+        if (mInErrorState) {
+            return UNKNOWN_ERROR;
+        }
+        if (mHasDequeuedBuffer) {
+            return OK;
+        }
+        if constexpr (DISABLE_BUFFER_PREFETCH) {
+            return OK;
+        }
+    }
+
+    // TODO: Update this to better handle when requested dimensions have changed
+    // Currently the driver does this via query + perform but that's after we've already
+    // reserved a buffer. Should we do that logic instead? Or should we drop
+    // the backing Surface to the ground and go full manual on the IGraphicBufferProducer instead?
+
+    int fenceFd = -1;
+    ANativeWindowBuffer* buffer = nullptr;
+    int result = callProtected(mSurface, dequeueBuffer, &buffer, &fenceFd);
+
+    {
+        std::lock_guard _lock{mMutex};
+        LOG_ALWAYS_FATAL_IF(mReservedBuffer, "race condition in reserveNext");
+        mReservedBuffer = buffer;
+        mReservedFenceFd.reset(fenceFd);
+    }
+
+    return result;
+}
+
+void ReliableSurface::clearReservedBuffer() {
+    ANativeWindowBuffer* buffer = nullptr;
+    int releaseFd = -1;
+    {
+        std::lock_guard _lock{mMutex};
+        if (mReservedBuffer) {
+            ALOGW("Reserved buffer %p was never used", mReservedBuffer);
+            buffer = mReservedBuffer;
+            releaseFd = mReservedFenceFd.release();
+        }
+        mReservedBuffer = nullptr;
+        mReservedFenceFd.reset();
+        mHasDequeuedBuffer = false;
+    }
+    if (buffer) {
+        callProtected(mSurface, cancelBuffer, buffer, releaseFd);
+    }
+}
+
+int ReliableSurface::cancelBuffer(ANativeWindowBuffer* buffer, int fenceFd) {
+    clearReservedBuffer();
+    if (isFallbackBuffer(buffer)) {
+        if (fenceFd > 0) {
+            close(fenceFd);
+        }
+        return OK;
+    }
+    int result = callProtected(mSurface, cancelBuffer, buffer, fenceFd);
+    return result;
+}
+
+int ReliableSurface::dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd) {
+    {
+        std::lock_guard _lock{mMutex};
+        if (mReservedBuffer) {
+            *buffer = mReservedBuffer;
+            *fenceFd = mReservedFenceFd.release();
+            mReservedBuffer = nullptr;
+            return OK;
+        }
+    }
+
+    int result = callProtected(mSurface, dequeueBuffer, buffer, fenceFd);
+    if (result != OK) {
+        ALOGW("dequeueBuffer failed, error = %d; switching to fallback", result);
+        *buffer = acquireFallbackBuffer();
+        *fenceFd = -1;
+        return *buffer ? OK : INVALID_OPERATION;
+    } else {
+        std::lock_guard _lock{mMutex};
+        mHasDequeuedBuffer = true;
+    }
+    return OK;
+}
+
+int ReliableSurface::queueBuffer(ANativeWindowBuffer* buffer, int fenceFd) {
+    clearReservedBuffer();
+
+    if (isFallbackBuffer(buffer)) {
+        if (fenceFd > 0) {
+            close(fenceFd);
+        }
+        return OK;
+    }
+
+    int result = callProtected(mSurface, queueBuffer, buffer, fenceFd);
+    return result;
+}
+
+bool ReliableSurface::isFallbackBuffer(const ANativeWindowBuffer* windowBuffer) const {
+    if (!mScratchBuffer || !windowBuffer) {
+        return false;
+    }
+    ANativeWindowBuffer* scratchBuffer =
+            AHardwareBuffer_to_ANativeWindowBuffer(mScratchBuffer.get());
+    return windowBuffer == scratchBuffer;
+}
+
+ANativeWindowBuffer* ReliableSurface::acquireFallbackBuffer() {
+    std::lock_guard _lock{mMutex};
+    mInErrorState = true;
+
+    if (mScratchBuffer) {
+        return AHardwareBuffer_to_ANativeWindowBuffer(mScratchBuffer.get());
+    }
+
+    AHardwareBuffer_Desc desc;
+    desc.usage = mUsage;
+    desc.format = mFormat;
+    desc.width = 1;
+    desc.height = 1;
+    desc.layers = 1;
+    desc.rfu0 = 0;
+    desc.rfu1 = 0;
+    AHardwareBuffer* newBuffer = nullptr;
+    int err = AHardwareBuffer_allocate(&desc, &newBuffer);
+    if (err) {
+        // Allocate failed, that sucks
+        ALOGW("Failed to allocate scratch buffer, error=%d", err);
+        return nullptr;
+    }
+    mScratchBuffer.reset(newBuffer);
+    return AHardwareBuffer_to_ANativeWindowBuffer(newBuffer);
+}
+
+Surface* ReliableSurface::getWrapped(const ANativeWindow* window) {
+    return getSelf(window)->mSurface.get();
+}
+
+int ReliableSurface::hook_setSwapInterval(ANativeWindow* window, int interval) {
+    return callProtected(getWrapped(window), setSwapInterval, interval);
+}
+
+int ReliableSurface::hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer,
+                                        int* fenceFd) {
+    return getSelf(window)->dequeueBuffer(buffer, fenceFd);
+}
+
+int ReliableSurface::hook_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer,
+                                       int fenceFd) {
+    return getSelf(window)->cancelBuffer(buffer, fenceFd);
+}
+
+int ReliableSurface::hook_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer,
+                                      int fenceFd) {
+    return getSelf(window)->queueBuffer(buffer, fenceFd);
+}
+
+int ReliableSurface::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
+                                                   ANativeWindowBuffer** buffer) {
+    ANativeWindowBuffer* buf;
+    int fenceFd = -1;
+    int result = window->dequeueBuffer(window, &buf, &fenceFd);
+    if (result != OK) {
+        return result;
+    }
+    sp<Fence> fence(new Fence(fenceFd));
+    int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED");
+    if (waitResult != OK) {
+        ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an error: %d", waitResult);
+        window->cancelBuffer(window, buf, -1);
+        return waitResult;
+    }
+    *buffer = buf;
+    return result;
+}
+
+int ReliableSurface::hook_cancelBuffer_DEPRECATED(ANativeWindow* window,
+                                                  ANativeWindowBuffer* buffer) {
+    return window->cancelBuffer(window, buffer, -1);
+}
+
+int ReliableSurface::hook_lockBuffer_DEPRECATED(ANativeWindow* window,
+                                                ANativeWindowBuffer* buffer) {
+    // This method is a no-op in Surface as well
+    return OK;
+}
+
+int ReliableSurface::hook_queueBuffer_DEPRECATED(ANativeWindow* window,
+                                                 ANativeWindowBuffer* buffer) {
+    return window->queueBuffer(window, buffer, -1);
+}
+
+int ReliableSurface::hook_query(const ANativeWindow* window, int what, int* value) {
+    return getWrapped(window)->query(what, value);
+}
+
+int ReliableSurface::hook_perform(ANativeWindow* window, int operation, ...) {
+    // Drop the reserved buffer if there is one since this (probably) mutated buffer dimensions
+    // TODO: Filter to things that only affect the reserved buffer
+    // TODO: Can we mutate the reserved buffer in some cases?
+    getSelf(window)->clearReservedBuffer();
+    va_list args;
+    va_start(args, operation);
+    int result = callProtected(getWrapped(window), perform, operation, args);
+    va_end(args);
+
+    switch (operation) {
+        case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
+        case NATIVE_WINDOW_SET_USAGE:
+        case NATIVE_WINDOW_SET_USAGE64:
+            va_start(args, operation);
+            getSelf(window)->perform(operation, args);
+            va_end(args);
+            break;
+        default:
+            break;
+    }
+
+    return result;
+}
+
+};  // namespace android::uirenderer::renderthread
\ No newline at end of file
diff --git a/libs/hwui/renderthread/ReliableSurface.h b/libs/hwui/renderthread/ReliableSurface.h
new file mode 100644
index 0000000..0bfc72e
--- /dev/null
+++ b/libs/hwui/renderthread/ReliableSurface.h
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <gui/Surface.h>
+#include <utils/Macros.h>
+#include <utils/StrongPointer.h>
+
+#include <memory>
+
+namespace android::uirenderer::renderthread {
+
+class ReliableSurface : public ANativeObjectBase<ANativeWindow, ReliableSurface, RefBase> {
+    PREVENT_COPY_AND_ASSIGN(ReliableSurface);
+
+public:
+    ReliableSurface(sp<Surface>&& surface);
+    ~ReliableSurface();
+
+    void setDequeueTimeout(nsecs_t timeout) { mSurface->setDequeueTimeout(timeout); }
+
+    int reserveNext();
+
+    void allocateBuffers() { mSurface->allocateBuffers(); }
+
+    int query(int what, int* value) const { return mSurface->query(what, value); }
+
+    nsecs_t getLastDequeueStartTime() const { return mSurface->getLastDequeueStartTime(); }
+
+    uint64_t getNextFrameNumber() const { return mSurface->getNextFrameNumber(); }
+
+private:
+    const sp<Surface> mSurface;
+
+    mutable std::mutex mMutex;
+
+    uint64_t mUsage = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
+    PixelFormat mFormat = PIXEL_FORMAT_RGBA_8888;
+    std::unique_ptr<AHardwareBuffer, void (*)(AHardwareBuffer*)> mScratchBuffer{
+            nullptr, AHardwareBuffer_release};
+    ANativeWindowBuffer* mReservedBuffer = nullptr;
+    base::unique_fd mReservedFenceFd;
+    bool mHasDequeuedBuffer = false;
+    bool mInErrorState = false;
+
+    bool isFallbackBuffer(const ANativeWindowBuffer* windowBuffer) const;
+    ANativeWindowBuffer* acquireFallbackBuffer();
+    void clearReservedBuffer();
+
+    void perform(int operation, va_list args);
+    int cancelBuffer(ANativeWindowBuffer* buffer, int fenceFd);
+    int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
+    int queueBuffer(ANativeWindowBuffer* buffer, int fenceFd);
+
+    static Surface* getWrapped(const ANativeWindow*);
+
+    // ANativeWindow hooks
+    static int hook_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd);
+    static int hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer,
+                                  int* fenceFd);
+    static int hook_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd);
+
+    static int hook_perform(ANativeWindow* window, int operation, ...);
+    static int hook_query(const ANativeWindow* window, int what, int* value);
+    static int hook_setSwapInterval(ANativeWindow* window, int interval);
+
+    static int hook_cancelBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer);
+    static int hook_dequeueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer** buffer);
+    static int hook_lockBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer);
+    static int hook_queueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer);
+};
+
+};  // namespace android::uirenderer::renderthread
\ No newline at end of file
diff --git a/libs/hwui/tests/unit/FatalTestCanvas.h b/libs/hwui/tests/unit/FatalTestCanvas.h
index 89f0c52..146662b 100644
--- a/libs/hwui/tests/unit/FatalTestCanvas.h
+++ b/libs/hwui/tests/unit/FatalTestCanvas.h
@@ -30,18 +30,6 @@
     void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) {
         ADD_FAILURE() << "onDrawDRRect not expected in this test";
     }
-    void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
-                    const SkPaint& paint) {
-        ADD_FAILURE() << "onDrawText not expected in this test";
-    }
-    void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
-                       const SkPaint& paint) {
-        ADD_FAILURE() << "onDrawPosText not expected in this test";
-    }
-    void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
-                        const SkPaint& paint) {
-        ADD_FAILURE() << "onDrawPosTextH not expected in this test";
-    }
     void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
                            const SkRect* cullRect, const SkPaint& paint) {
         ADD_FAILURE() << "onDrawTextRSXform not expected in this test";
diff --git a/libs/incident/src/IncidentReportArgs.cpp b/libs/incident/src/IncidentReportArgs.cpp
index fbc21e5..26261ef 100644
--- a/libs/incident/src/IncidentReportArgs.cpp
+++ b/libs/incident/src/IncidentReportArgs.cpp
@@ -18,7 +18,7 @@
 
 #include <android/os/IncidentReportArgs.h>
 
-#include <cutils/log.h>
+#include <log/log.h>
 
 namespace android {
 namespace os {
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 3e3e651..24d2725 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -670,27 +670,43 @@
     }
 
     /**
-     * Private constructor with an ignored argument to differentiate from the removed default ctor
-     * @param ignoredArgument
-     */
-    private AudioFormat(int ignoredArgument) {
-    }
-
-    /**
      * Constructor used by the JNI.  Parameters are not checked for validity.
      */
     // Update sound trigger JNI in core/jni/android_hardware_SoundTrigger.cpp when modifying this
     // constructor
     @UnsupportedAppUsage
     private AudioFormat(int encoding, int sampleRate, int channelMask, int channelIndexMask) {
-        mEncoding = encoding;
-        mSampleRate = sampleRate;
-        mChannelMask = channelMask;
-        mChannelIndexMask = channelIndexMask;
-        mPropertySetMask = AUDIO_FORMAT_HAS_PROPERTY_ENCODING |
-                AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE |
-                AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK |
-                AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK;
+        this(
+             AUDIO_FORMAT_HAS_PROPERTY_ENCODING
+             | AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE
+             | AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK
+             | AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK,
+             encoding, sampleRate, channelMask, channelIndexMask
+             );
+    }
+
+    private AudioFormat(int propertySetMask,
+            int encoding, int sampleRate, int channelMask, int channelIndexMask) {
+        mPropertySetMask = propertySetMask;
+        mEncoding = (propertySetMask & AUDIO_FORMAT_HAS_PROPERTY_ENCODING) != 0
+                ? encoding : ENCODING_INVALID;
+        mSampleRate = (propertySetMask & AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE) != 0
+                ? sampleRate : SAMPLE_RATE_UNSPECIFIED;
+        mChannelMask = (propertySetMask & AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK) != 0
+                ? channelMask : CHANNEL_INVALID;
+        mChannelIndexMask = (propertySetMask & AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK) != 0
+                ? channelIndexMask : CHANNEL_INVALID;
+
+        // Compute derived values.
+
+        final int channelIndexCount = Integer.bitCount(getChannelIndexMask());
+        int channelCount = channelCountFromOutChannelMask(getChannelMask());
+        if (channelCount == 0) {
+            channelCount = channelIndexCount;
+        } else if (channelCount != channelIndexCount && channelIndexCount != 0) {
+            channelCount = 0; // position and index channel count mismatch
+        }
+        mChannelCount = channelCount;
     }
 
     /** @hide */
@@ -704,14 +720,20 @@
     /** @hide */
     public final static int AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK = 0x1 << 3;
 
+    // This is an immutable class, all member variables are final.
+
+    // Essential values.
     @UnsupportedAppUsage
-    private int mEncoding;
+    private final int mEncoding;
     @UnsupportedAppUsage
-    private int mSampleRate;
+    private final int mSampleRate;
     @UnsupportedAppUsage
-    private int mChannelMask;
-    private int mChannelIndexMask;
-    private int mPropertySetMask;
+    private final int mChannelMask;
+    private final int mChannelIndexMask;
+    private final int mPropertySetMask;
+
+    // Derived values computed in the constructor, cached here.
+    private final int mChannelCount;
 
     /**
      * Return the encoding.
@@ -721,9 +743,6 @@
      * {@link AudioFormat#ENCODING_INVALID} if not set.
      */
     public int getEncoding() {
-        if ((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_ENCODING) == 0) {
-            return ENCODING_INVALID;
-        }
         return mEncoding;
     }
 
@@ -745,9 +764,6 @@
      * {@link AudioFormat#CHANNEL_INVALID} if not set.
      */
     public int getChannelMask() {
-        if ((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK) == 0) {
-            return CHANNEL_INVALID;
-        }
         return mChannelMask;
     }
 
@@ -760,9 +776,6 @@
      * {@link AudioFormat#CHANNEL_INVALID} if not set or an invalid mask was used.
      */
     public int getChannelIndexMask() {
-        if ((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK) == 0) {
-            return CHANNEL_INVALID;
-        }
         return mChannelIndexMask;
     }
 
@@ -772,14 +785,7 @@
      * Zero is returned if both the channel position mask and the channel index mask are not set.
      */
     public int getChannelCount() {
-        final int channelIndexCount = Integer.bitCount(getChannelIndexMask());
-        int channelCount = channelCountFromOutChannelMask(getChannelMask());
-        if (channelCount == 0) {
-            channelCount = channelIndexCount;
-        } else if (channelCount != channelIndexCount && channelIndexCount != 0) {
-            channelCount = 0; // position and index channel count mismatch
-        }
-        return channelCount;
+        return mChannelCount;
     }
 
     /** @hide */
@@ -790,7 +796,7 @@
     /** @hide */
     public String toLogFriendlyString() {
         return String.format("%dch %dHz %s",
-                getChannelCount(), mSampleRate, toLogFriendlyEncoding(mEncoding));
+                mChannelCount, mSampleRate, toLogFriendlyEncoding(mEncoding));
     }
 
     /**
@@ -839,14 +845,13 @@
          * @return a new {@link AudioFormat} object
          */
         public AudioFormat build() {
-            AudioFormat af = new AudioFormat(1980/*ignored*/);
-            af.mEncoding = mEncoding;
-            // not calling setSampleRate is equivalent to calling
-            // setSampleRate(SAMPLE_RATE_UNSPECIFIED)
-            af.mSampleRate = mSampleRate;
-            af.mChannelMask = mChannelMask;
-            af.mChannelIndexMask = mChannelIndexMask;
-            af.mPropertySetMask = mPropertySetMask;
+            AudioFormat af = new AudioFormat(
+                    mPropertySetMask,
+                    mEncoding,
+                    mSampleRate,
+                    mChannelMask,
+                    mChannelIndexMask
+                    );
             return af;
         }
 
@@ -1049,11 +1054,13 @@
     }
 
     private AudioFormat(Parcel in) {
-        mPropertySetMask = in.readInt();
-        mEncoding = in.readInt();
-        mSampleRate = in.readInt();
-        mChannelMask = in.readInt();
-        mChannelIndexMask = in.readInt();
+        this(
+             in.readInt(), // propertySetMask
+             in.readInt(), // encoding
+             in.readInt(), // sampleRate
+             in.readInt(), // channelMask
+             in.readInt()  // channelIndexMask
+            );
     }
 
     public static final Parcelable.Creator<AudioFormat> CREATOR =
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 2c4ec3a..e4d4795 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -3365,7 +3365,7 @@
                                                 int offsetInFloats, int sizeInFloats, int format,
                                                 boolean isBlocking);
 
-    private native final int native_write_native_bytes(Object audioData,
+    private native final int native_write_native_bytes(ByteBuffer audioData,
             int positionInBytes, int sizeInBytes, int format, boolean blocking);
 
     private native final int native_reload_static();
diff --git a/media/java/android/media/CallbackDataSourceDesc.java b/media/java/android/media/CallbackDataSourceDesc.java
index cb9669b..cd36414 100644
--- a/media/java/android/media/CallbackDataSourceDesc.java
+++ b/media/java/android/media/CallbackDataSourceDesc.java
@@ -21,10 +21,8 @@
 /**
  * Structure of data source descriptor for sources using callback.
  *
- * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)},
- * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} and
- * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}
- * to set data source for playback.
+ * Used by {@link MediaPlayer2#setDataSource}, {@link MediaPlayer2#setNextDataSource} and
+ * {@link MediaPlayer2#setNextDataSources} to set data source for playback.
  *
  * <p>Users should use {@link Builder} to create {@link CallbackDataSourceDesc}.
  *
@@ -37,7 +35,6 @@
 
     /**
      * Return the DataSourceCallback of this data source.
-     * It's meaningful only when {@code getType} returns {@link #TYPE_CALLBACK}.
      * @return the DataSourceCallback of this data source
      */
     public DataSourceCallback getDataSourceCallback() {
diff --git a/media/java/android/media/DataSourceDesc.java b/media/java/android/media/DataSourceDesc.java
index 9109ea5..7fc6f79 100644
--- a/media/java/android/media/DataSourceDesc.java
+++ b/media/java/android/media/DataSourceDesc.java
@@ -21,10 +21,8 @@
 /**
  * Base class of data source descriptor.
  *
- * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)},
- * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} and
- * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}
- * to set data source for playback.
+ * Used by {@link MediaPlayer2#setDataSource}, {@link MediaPlayer2#setNextDataSource} and
+ * {@link MediaPlayer2#setNextDataSources} to set data source for playback.
  *
  * <p>Users should use subclasses' builder to change {@link DataSourceDesc}.
  *
diff --git a/media/java/android/media/FileDataSourceDesc.java b/media/java/android/media/FileDataSourceDesc.java
index 14ef180..aca8dbe 100644
--- a/media/java/android/media/FileDataSourceDesc.java
+++ b/media/java/android/media/FileDataSourceDesc.java
@@ -25,10 +25,8 @@
 /**
  * Structure of data source descriptor for sources using file descriptor.
  *
- * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)},
- * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} and
- * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}
- * to set data source for playback.
+ * Used by {@link MediaPlayer2#setDataSource}, {@link MediaPlayer2#setNextDataSource} and
+ * {@link MediaPlayer2#setNextDataSources} to set data source for playback.
  *
  * <p>Users should use {@link Builder} to create {@link FileDataSourceDesc}.
  *
@@ -165,9 +163,9 @@
          * Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be
          * seekable (N.B. a LocalSocket is not seekable). When the {@link FileDataSourceDesc}
          * created by this builder is passed to {@link MediaPlayer2} via
-         * {@link MediaPlayer2#setDataSource(DataSourceDesc)},
-         * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} or
-         * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}, MediaPlayer2 will
+         * {@link MediaPlayer2#setDataSource},
+         * {@link MediaPlayer2#setNextDataSource} or
+         * {@link MediaPlayer2#setNextDataSources}, MediaPlayer2 will
          * close the ParcelFileDescriptor.
          *
          * @param pfd the ParcelFileDescriptor for the file to play
@@ -185,9 +183,9 @@
          * Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be
          * seekable (N.B. a LocalSocket is not seekable). When the {@link FileDataSourceDesc}
          * created by this builder is passed to {@link MediaPlayer2} via
-         * {@link MediaPlayer2#setDataSource(DataSourceDesc)},
-         * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} or
-         * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}, MediaPlayer2 will
+         * {@link MediaPlayer2#setDataSource},
+         * {@link MediaPlayer2#setNextDataSource} or
+         * {@link MediaPlayer2#setNextDataSources}, MediaPlayer2 will
          * close the ParcelFileDescriptor.
          *
          * Any negative number for offset is treated as 0.
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index e6ad444..9038f72 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -98,11 +98,10 @@
  * <p>The MediaPlayer2 object has five states:</p>
  * <ol>
  *     <li><p>{@link #PLAYER_STATE_IDLE}: MediaPlayer2 is in the <strong>Idle</strong>
- *         state after you create it using
- *         {@link #create()}, or after calling {@link #reset()}.</p>
+ *         state after it's created, or after calling {@link #reset()}.</p>
  *
  *         <p>While in this state, you should call
- *         {@link #setDataSource(DataSourceDesc2) setDataSource()}. It is a good
+ *         {@link #setDataSource setDataSource}. It is a good
  *         programming practice to register an {@link EventCallback#onCallCompleted onCallCompleted}
  *         <a href="#Callbacks">callback</a> and watch for {@link #CALL_STATUS_BAD_VALUE} and
  *         {@link #CALL_STATUS_ERROR_IO}, which might be caused by <code>setDataSource</code>.
@@ -134,7 +133,7 @@
  *         while streaming audio/video.</p>
  *
  *         <p> When the playback reaches the end of stream, the behavior depends on whether or
- *         not you've enabled looping by calling {@link #loopCurrent(boolean) loopCurrent}:</p>
+ *         not you've enabled looping by calling {@link #loopCurrent}:</p>
  *         <ul>
  *         <li>If the looping mode was set to <code>false</code>, the player will transfer
  *         to the <strong>Paused</strong> state. If you registered an {@link EventCallback#onInfo
@@ -161,15 +160,15 @@
  *          <p>If you register an {@link EventCallback#onError onError}}
  *          <a href="#Callbacks">callback</a>,
  *          the callback will be performed when entering the state. When programming errors happen,
- *          such as calling {@link #prepare() prepare} and
- *          {@link #setDataSource(DataSourceDesc) setDataSource} methods
+ *          such as calling {@link #prepare()} and
+ *          {@link #setDataSource} methods
  *          from an <a href="#InvalidStates">invalid state</a>, the callback is called with
  *          {@link #CALL_STATUS_INVALID_OPERATION}. The MediaPlayer2 object enters the
  *          <strong>Error</strong> state whether or not a callback exists. </p>
  *
  *          <p>To recover from an error and reuse a MediaPlayer2 object that is in the <strong>
  *          Error</strong> state,
- *          call {@link #reset() reset}. The object will return to the <strong>Idle</strong>
+ *          call {@link #reset()}. The object will return to the <strong>Idle</strong>
  *          state and all state information will be lost.</p>
  *          </li>
  * </ol>
@@ -180,26 +179,26 @@
  *
  * <li>Use <a href="#Callbacks">callbacks</a> to respond to state changes and errors.</li>
  *
- * <li>When  a MediaPlayer2 object is no longer being used, call {@link #close() close} as soon as
+ * <li>When  a MediaPlayer2 object is no longer being used, call {@link #close()} as soon as
  * possible to release the resources used by the internal player engine associated with the
- * MediaPlayer2. Failure to call {@link #close() close} may cause subsequent instances of
+ * MediaPlayer2. Failure to call {@link #close()} may cause subsequent instances of
  * MediaPlayer2 objects to fallback to software implementations or fail altogether.
  * You cannot use MediaPlayer2
- * after you call {@link #close() close}. There is no way to bring it back to any other state.</li>
+ * after you call {@link #close()}. There is no way to bring it back to any other state.</li>
  *
  * <li>The current playback position can be retrieved with a call to
- * {@link #getCurrentPosition() getCurrentPosition},
+ * {@link #getCurrentPosition()},
  * which is helpful for applications such as a Music player that need to keep track of the playback
  * progress.</li>
  *
- * <li>The playback position can be adjusted with a call to {@link #seekTo seekTo}. Although the
- * asynchronous {@link #seekTo seekTo} call returns right away, the actual seek operation may take a
+ * <li>The playback position can be adjusted with a call to {@link #seekTo}. Although the
+ * asynchronous {@link #seekTo} call returns right away, the actual seek operation may take a
  * while to finish, especially for audio/video being streamed. If you register an
  * {@link EventCallback#onCallCompleted onCallCompleted} <a href="#Callbacks">callback</a>,
  * the callback is
  * called When the seek operation completes with {@link #CALL_COMPLETED_SEEK_TO}.</li>
  *
- * <li>You can call {@link #seekTo seekTo} from the <strong>Paused</strong> state.
+ * <li>You can call {@link #seekTo} from the <strong>Paused</strong> state.
  * In this case, if you are playing a video stream and
  * the requested position is valid  one video frame is displayed.</li>
  *
@@ -208,13 +207,13 @@
  * <h3 id="InvalidStates">Invalid method calls</h3>
  *
  * <p>The only methods you safely call from the <strong>Error</strong> state are
- * {@link #close() close},
- * {@link #reset() reset},
- * {@link #notifyWhenCommandLabelReached notifyWhenCommandLabelReached},
- * {@link #clearPendingCommands() clearPendingCommands},
- * {@link #setEventCallback setEventCallback},
- * {@link #clearEventCallback() clearEventCallback}
- * and {@link #getState() getState}.
+ * {@link #close},
+ * {@link #reset},
+ * {@link #notifyWhenCommandLabelReached},
+ * {@link #clearPendingCommands},
+ * {@link #registerEventCallback},
+ * {@link #unregisterEventCallback}
+ * and {@link #getState}.
  * Any other methods might throw an exception, return meaningless data, or invoke a
  * {@link EventCallback#onCallCompleted onCallCompleted} with an error code.</p>
  *
@@ -248,8 +247,7 @@
  * <h3 id="Callbacks">Callbacks</h3>
  * <p>Many errors do not result in a transition to the  <strong>Error</strong> state.
  * It is good programming practice to register callback listeners using
- * {@link #setEventCallback(Executor, EventCallback) setEventCallback} and
- * {@link #setDrmEventCallback(Executor, DrmEventCallback) setDrmEventCallback}).
+ * {@link #registerEventCallback}.
  * You can receive a callback at any time and from any state.</p>
  *
  * <p>If it's important for your app to respond to state changes (for instance, to update the
@@ -1445,7 +1443,7 @@
      * @return the size of the video. The width and height of size could be 0 if there is no video,
      * no display surface was set, or the size has not been determined yet.
      * The {@code EventCallback} can be registered via
-     * {@link #setEventCallback(Executor, EventCallback)} to provide a
+     * {@link #registerEventCallback(Executor, EventCallback)} to provide a
      * notification {@code EventCallback.onVideoSizeChanged} when the size
      * is available.
      */
@@ -1713,10 +1711,12 @@
     public MediaTimestamp getTimestamp() {
         try {
             // TODO: get the timestamp from native side
-            return new MediaTimestamp(
-                    getCurrentPosition() * 1000L,
-                    System.nanoTime(),
-                    getState() == PLAYER_STATE_PLAYING ? getPlaybackParams().getSpeed() : 0.f);
+            return new MediaTimestamp.Builder()
+                    .setMediaTimestamp(
+                        getCurrentPosition() * 1000L,
+                        System.nanoTime(),
+                        getState() == PLAYER_STATE_PLAYING ? getPlaybackParams().getSpeed() : 0.f)
+                    .build();
         } catch (IllegalStateException e) {
             return null;
         }
@@ -2400,11 +2400,13 @@
                             return;
                         }
                         Iterator<Value> in = playerMsg.getValuesList().iterator();
-                        SubtitleData data = new SubtitleData(
-                                in.next().getInt32Value(),  // trackIndex
-                                in.next().getInt64Value(),  // startTimeUs
-                                in.next().getInt64Value(),  // durationUs
-                                in.next().getBytesValue().toByteArray());  // data
+                        SubtitleData data = new SubtitleData.Builder()
+                                .setSubtitleData(
+                                    in.next().getInt32Value(),  // trackIndex
+                                    in.next().getInt64Value(),  // startTimeUs
+                                    in.next().getInt64Value(),  // durationUs
+                                    in.next().getBytesValue().toByteArray())  // data
+                                .build();
                         sendEvent(new EventNotifier() {
                             @Override
                             public void notify(EventCallback callback) {
@@ -2428,9 +2430,11 @@
                             return;
                         }
                         Iterator<Value> in = playerMsg.getValuesList().iterator();
-                        data = new TimedMetaData(
-                                in.next().getInt64Value(),  // timestampUs
-                                in.next().getBytesValue().toByteArray());  // metaData
+                        data = new TimedMetaData.Builder()
+                                .setTimedMetaData(
+                                    in.next().getInt64Value(),  // timestampUs
+                                    in.next().getBytesValue().toByteArray())  // metaData
+                                .build();
                     } else {
                         data = null;
                     }
@@ -3060,7 +3064,7 @@
     public static final int CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED =
             SEPARATE_CALL_COMPLETED_CALLBACK_START;
 
-    /** The player just completed a call {@link #prepareDrm(DataSourceDesc, UUID)}.
+    /** The player just completed a call {@link #prepareDrm}.
      * @see DrmEventCallback#onDrmPrepared
      * @hide
      */
@@ -3138,9 +3142,10 @@
     public static final int CALL_STATUS_SKIPPED = 5;
 
     /** Status code represents that DRM operation is called before preparing a DRM scheme through
-     *  {@link #prepareDrm(DataSourceDesc, UUID)}.
+     *  {@code prepareDrm}.
      * @see EventCallback#onCallCompleted
      */
+    // TODO: change @code to @link when DRM is unhidden
     public static final int CALL_STATUS_NO_DRM_SCHEME = 6;
 
     /**
@@ -3186,7 +3191,7 @@
      * Register a callback to be invoked for configuration of the DRM object before
      * the session is created.
      * The callback will be invoked synchronously during the execution
-     * of {@link #prepareDrm(DataSourceDesc, UUID)}.
+     * of {@link #prepareDrm}.
      *
      * @param listener the callback that will be run
      * @hide
diff --git a/media/java/android/media/MediaTimestamp.java b/media/java/android/media/MediaTimestamp.java
index e079a8e..03e454c 100644
--- a/media/java/android/media/MediaTimestamp.java
+++ b/media/java/android/media/MediaTimestamp.java
@@ -16,6 +16,9 @@
 
 package android.media;
 
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+
 /**
  * An immutable object that represents the linear correlation between the media time
  * and the system time. It contains the media clock rate, together with the media timestamp
@@ -117,4 +120,71 @@
                 + " clockRate=" + clockRate
                 + "}";
     }
+
+    /**
+     * Builder class for {@link MediaTimestamp} objects.
+     * <p> Here is an example where <code>Builder</code> is used to define the
+     * {@link MediaTimestamp}:
+     *
+     * <pre class="prettyprint">
+     * MediaTimestamp mts = new MediaTimestamp.Builder()
+     *         .setMediaTimestamp(mediaTime, systemTime, rate)
+     *         .build();
+     * </pre>
+     * @hide
+     */
+    @SystemApi
+    public static class Builder {
+        long mMediaTimeUs;
+        long mNanoTime;
+        float mClockRate = 1.0f;
+
+        /**
+         * Constructs a new Builder with the defaults.
+         */
+        public Builder() {
+        }
+
+        /**
+         * Constructs a new Builder from a given {@link MediaTimestamp} instance
+         * @param mts the {@link MediaTimestamp} object whose data will be reused
+         * in the new Builder.
+         */
+        public Builder(@NonNull MediaTimestamp mts) {
+            if (mts == null) {
+                throw new IllegalArgumentException("null MediaTimestamp is not allowed");
+            }
+            mMediaTimeUs = mts.mediaTimeUs;
+            mNanoTime = mts.nanoTime;
+            mClockRate = mts.clockRate;
+        }
+
+        /**
+         * Combines all of the fields that have been set and return a new
+         * {@link MediaTimestamp} object.
+         *
+         * @return a new {@link MediaTimestamp} object
+         */
+        public @NonNull MediaTimestamp build() {
+            return new MediaTimestamp(mMediaTimeUs, mNanoTime, mClockRate);
+        }
+
+        /**
+         * Sets the info of media timestamp.
+         *
+         * @param mediaTimeUs the media time of the anchor in microseconds
+         * @param nanoTime the {@link java.lang.System#nanoTime system time} corresponding to
+         *     the media time in nanoseconds.
+         * @param clockRate the rate of the media clock in relation to the system time.
+         * @return the same Builder instance.
+         */
+        public @NonNull Builder setMediaTimestamp(
+                long mediaTimeUs, long nanoTime, float clockRate) {
+            mMediaTimeUs = mediaTimeUs;
+            mNanoTime = nanoTime;
+            mClockRate = clockRate;
+
+            return this;
+        }
+    }
 }
diff --git a/media/java/android/media/TimedMetaData.java b/media/java/android/media/TimedMetaData.java
index bcc18ef..2a89888 100644
--- a/media/java/android/media/TimedMetaData.java
+++ b/media/java/android/media/TimedMetaData.java
@@ -148,7 +148,7 @@
          *     It should not be null.
          * @return the same Builder instance.
          */
-        public @NonNull Builder setTimedMetaData(int timestamp, @NonNull byte[] metaData) {
+        public @NonNull Builder setTimedMetaData(long timestamp, @NonNull byte[] metaData) {
             if (metaData == null) {
                 throw new IllegalArgumentException("null metaData is not allowed");
             }
diff --git a/media/java/android/media/UriDataSourceDesc.java b/media/java/android/media/UriDataSourceDesc.java
index e39f53c..4eb9e8d 100644
--- a/media/java/android/media/UriDataSourceDesc.java
+++ b/media/java/android/media/UriDataSourceDesc.java
@@ -32,10 +32,8 @@
 /**
  * Structure of data source descriptor for sources using URI.
  *
- * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)},
- * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} and
- * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}
- * to set data source for playback.
+ * Used by {@link MediaPlayer2#setDataSource}, {@link MediaPlayer2#setNextDataSource} and
+ * {@link MediaPlayer2#setNextDataSources} to set data source for playback.
  *
  * <p>Users should use {@link Builder} to change {@link UriDataSourceDesc}.
  *
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index d91cf87..6a06dd0 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -96,15 +96,9 @@
      * @return The binder object from the system
      * @hide
      */
-    @SystemApi
     public @NonNull ISession createSession(@NonNull MediaSession.CallbackStub cbStub,
-            @NonNull String tag, int userId) {
-        try {
-            return mService.createSession(mContext.getPackageName(), cbStub, tag, userId);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-        return null;
+            @NonNull String tag, int userId) throws RemoteException {
+        return mService.createSession(mContext.getPackageName(), cbStub, tag, userId);
     }
 
     /**
@@ -626,12 +620,24 @@
         private final int mUid;
         private final IBinder mCallerBinder;
 
+        /**
+         * Create a new remote user information.
+         *
+         * @param packageName The package name of the remote user
+         * @param pid The pid of the remote user
+         * @param uid The uid of the remote user
+         */
         public RemoteUserInfo(@NonNull String packageName, int pid, int uid) {
             this(packageName, pid, uid, null);
         }
 
         /**
-         * @hide
+         * Create a new remote user information.
+         *
+         * @param packageName The package name of the remote user
+         * @param pid The pid of the remote user
+         * @param uid The uid of the remote user
+         * @param callerBinder The binder of the remote user. Can be {@code null}.
          */
         public RemoteUserInfo(String packageName, int pid, int uid, IBinder callerBinder) {
             mPackageName = packageName;
diff --git a/packages/CaptivePortalLogin/res/values-af/strings.xml b/packages/CaptivePortalLogin/res/values-af/strings.xml
index cf4dc82..37acf45 100644
--- a/packages/CaptivePortalLogin/res/values-af/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-af/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Die netwerk waarby jy probeer aansluit, het sekuriteitkwessies."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Byvoorbeeld, die aanmeldbladsy behoort dalk nie aan die organisasie wat gewys word nie."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Gaan in elk geval deur blaaier voort"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Bladsy-inligting"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sekuriteitswaarskuwing"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Bekyk sertifikaat"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Hierdie sertifikaat is nie van \'n betroubare owerheid nie."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Die naam van die werf kom nie ooreen met die naam op die sertifikaat nie."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Hierdie sertifikaat het verval."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Hierdie sertifikaat is nog nie geldig nie."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Hierdie sertifikaat het \'n ongeldige datum."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Hierdie sertifikaat is ongeldig."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Onbekende sertifikaatfout."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Hierdie sertifikaat is nie van \'n betroubare owerheid nie."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Die naam van die werf stem nie ooreen met die naam op die sertifikaat nie."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Hierdie sertifikaat het verval."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Hierdie sertifikaat is nog nie geldig nie."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Hierdie sertifikaat het \'n ongeldige datum."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Hierdie sertifikaat is ongeldig."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Onbekende sertifikaatfout."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Sekuriteitswaarskuwing"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Bekyk sertifikaat"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adres:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Bladsy-inligting"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-am/strings.xml b/packages/CaptivePortalLogin/res/values-am/strings.xml
index cdcb5a5..4e35e19 100644
--- a/packages/CaptivePortalLogin/res/values-am/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-am/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"ለመቀላቀል እየሞከሩ ያሉት አውታረ መረብ የደህንነት ችግሮች አሉበት።"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"ለምሳሌ፣ የመግቢያ ገጹ የሚታየው ድርጅት ላይሆን ይችላል።"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ለማንኛውም በአሳሽ በኩል ይቀጥሉ"</string>
-    <string name="ok" msgid="1509280796718850364">"እሺ"</string>
-    <string name="page_info" msgid="4048529256302257195">"የገፅ መረጃ"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"አድራሻ:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"የደህንነት ቅንብሮች"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"ምስክሮች ይመልከቱ"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"ይህ ምስክር ከታማኝ ቦታ አይደለም።"</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"የጣቢያው ስም ከምስክር ወረቀቱ ስም ጋር አይዛመድም።"</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"ይህ ምስክር ጊዜው አልፏል"</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"ይህ ምስክር ገና ትክክል አይደለም።"</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"ይህ ምስክር ትክክለኛ ቀን አለው።"</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"ይህ ምስክር ትክክል ያልሆነ ነው።"</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"ያልታወቀ የምስክር ስህተት።"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"ይህ የእውቅና ማረጋገጫ ከታማኝ ቦታ አይደለም።"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"የጣቢያው ስም ከእውቅና ማረጋገጫው ስም ጋር አይዛመድም።"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"ይህ የእውቅና ማረጋገጫ ጊዜው አልፏል።"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"ይህ የእውቅና ማረጋገጫ ገና የሚሰራ አይደለም።"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"ይህ የእውቅና ማረጋገጫ ልክ ያልሆነ ቀን ነው ያለው።"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"ይህ የእውቅና ማረጋገጫ ልክ ያልሆነ ነው።"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"ያልታወቀ የእውቅና ማረጋገጫ ስህተት።"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"የደህንነት ቅንብሮች"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"የእውቅና ማረጋገጫን ይመልከቱ"</string>
+    <string name="ok" msgid="2817931639040794018">"እሺ"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"አድራሻ፦"</string>
+    <string name="page_info" msgid="4416941086705172545">"የገጽ መረጃ"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ar/strings.xml b/packages/CaptivePortalLogin/res/values-ar/strings.xml
index 7773eeb..9f3aefa 100644
--- a/packages/CaptivePortalLogin/res/values-ar/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ar/strings.xml
@@ -11,16 +11,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"الشبكة التي تحاول الانضمام إليها بها مشاكل أمنية."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"على سبيل المثال، قد لا تنتمي صفحة تسجيل الدخول إلى المنظمة المعروضة."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"المتابعة على أي حال عبر المتصفح"</string>
-    <string name="ok" msgid="1509280796718850364">"موافق"</string>
-    <string name="page_info" msgid="4048529256302257195">"معلومات الصفحة"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"العنوان:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"تحذير أمان"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"عرض الشهادة"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"هذه الشهادة ليست من جهة موثوق بها."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"لا يتطابق اسم الموقع مع الاسم على الشهادة."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"انتهت صلاحية هذه الشهادة."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"هذه الشهادة ليست صالحة بعد."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"تشتمل هذه الشهادة على تاريخ غير صالح."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"هذه الشهادة غير صالحة."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"حدث خطأ غير معروف بالشهادة."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"هذه الشهادة ليست من جهة موثوق بها."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"لا يتطابق اسم الموقع مع الاسم على الشهادة."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"انتهت صلاحية هذه الشهادة."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"هذه الشهادة ليست صالحة بعد."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"تشتمل هذه الشهادة على تاريخ غير صالح."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"هذه الشهادة غير صالحة."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"حدث خطأ غير معروف بالشهادة."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"تحذير أمني"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"عرض الشهادة"</string>
+    <string name="ok" msgid="2817931639040794018">"حسنًا"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"العنوان:"</string>
+    <string name="page_info" msgid="4416941086705172545">"معلومات الصفحة"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-as/strings.xml b/packages/CaptivePortalLogin/res/values-as/strings.xml
index 94c3147..696483c 100644
--- a/packages/CaptivePortalLogin/res/values-as/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-as/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"আপুনি সংযোগ কৰিবলৈ চেষ্টা কৰি থকা নেটৱৰ্কটোত সুৰক্ষাজনিত সমস্যা আছে।"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"উদাহৰণস্বৰূপে, আপোনাক দেখুওৱা লগ ইনৰ পৃষ্ঠাটো প্ৰতিষ্ঠানটোৰ নিজা নহ\'বও পাৰে।"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"তথাপি ব্ৰাউজাৰৰ জৰিয়তে অব্যাহত ৰাখক"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"এই প্ৰমাণপত্ৰখন কোনো বিশ্বাসী কর্তৃপক্ষৰ নহয়।"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"ৱেবচাইটটোৰ নাম আৰু প্ৰমাণপত্ৰখনত থকা নামটোৰ মিল নাই।"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"এই প্ৰমাণপত্ৰখনৰ ম্যাদ উকলি গৈছে।"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"এই প্ৰমাণপত্ৰখন এই পর্যন্ত মান্য হোৱা নাই।"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"এই প্ৰমাণপত্ৰখনত থকা তাৰিখটো মান্য নহয়।"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"এই প্ৰমাণপত্ৰখন মান্য নহয়।"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"প্ৰমাণপত্ৰত অজ্ঞাত আসোঁৱাহ।"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"সুৰক্ষা সম্পর্কীয় সতৰ্কতা"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"প্ৰমাণপত্ৰ চাওক"</string>
+    <string name="ok" msgid="2817931639040794018">"ঠিক আছে"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"ঠিকনা:"</string>
+    <string name="page_info" msgid="4416941086705172545">"পৃষ্ঠাৰ তথ্য"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-az/strings.xml b/packages/CaptivePortalLogin/res/values-az/strings.xml
index 44b406d..f002544 100644
--- a/packages/CaptivePortalLogin/res/values-az/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-az/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Qoşulmaq istədiyiniz şəbəkənin təhlükəsizlik problemləri var."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Məsələn, giriş səhifəsi göstərilən təşkilata aid olmaya bilər."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Hər bir halda brazuer ilə davam edin"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Bu sertifikat etibarlı orqan tərəfindən verilməyib."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Saytın adı sertifikatdakı ada uyğun deyil."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Bu sertifikatın müddəti bitib."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Bu sertifikat hələ etibarlı deyil."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Bu sertifikatın tarixi yanlışdır."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Bu sertifikat etibarsızdır."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Bilinməyən sertifikat xətası."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Təhlükəsizlik xəbərdarlığı"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Sertifikata baxın"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Ünvan:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Səhifə məlumatı"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-b+sr+Latn/strings.xml b/packages/CaptivePortalLogin/res/values-b+sr+Latn/strings.xml
index f2a6e07..401548b 100644
--- a/packages/CaptivePortalLogin/res/values-b+sr+Latn/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-b+sr+Latn/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Mreža kojoj pokušavate da se pridružite ima bezbednosnih problema."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Na primer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Ipak nastavi preko pregledača"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Ovaj sertifikat ne potiče iz pouzdanog izvora."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Naziv sajta se ne podudara sa nazivom na sertifikatu."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Ovaj sertifikat je istekao."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Ovaj sertifikat još uvek nije važeći."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Datum ovog sertifikata je nevažeći."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Ovaj sertifikat je nevažeći."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Nepoznata greška sertifikata."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Bezbednosno upozorenje"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Prikaži sertifikat"</string>
+    <string name="ok" msgid="2817931639040794018">"Potvrdi"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adresa:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informacije o stranici"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-be/strings.xml b/packages/CaptivePortalLogin/res/values-be/strings.xml
index 09ed1de..5f2bd90 100644
--- a/packages/CaptivePortalLogin/res/values-be/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-be/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"У сеткі, да якой вы спрабуеце далучыцца, ёсць праблемы з бяспекай."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Напрыклад, старонка ўваходу можа не належаць указанай арганізацыі."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Усё роўна працягнуць праз браўзер"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Гэты сертыфікат не выдадзены давераным цэнтрам."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Назва сайта не адпавядае назве ў сертыфікаце."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Тэрмін дзеяння сертыфіката мінуў."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Гэты сертыфікат яшчэ не дзейнічае."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Гэты сертыфікат мае несапраўдную дату."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Гэты сертыфікат несапраўдны."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Невядомая памылка сертыфіката."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Папярэджанне сістэмы бяспекі"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Прагледзець сертыфікат"</string>
+    <string name="ok" msgid="2817931639040794018">"ОК"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Адрас:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Інфармацыя пра старонку"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-bg/strings.xml b/packages/CaptivePortalLogin/res/values-bg/strings.xml
index 4dd8aa0..c5354e8 100644
--- a/packages/CaptivePortalLogin/res/values-bg/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-bg/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Мрежата, към която опитвате да се присъедините, има проблеми със сигурността."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Например страницата за вход може да не принадлежи на показаната организация."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Продължаване през браузър въпреки това"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Данни за страницата"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Адрес:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Предупреждение относно защитата"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Преглед на сертификата"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Сертификатът не е от надежден орган."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Името на сайта не съответства на името в сертификата."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Сертификатът е изтекъл."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Сертификатът още не е валиден."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Този сертификат е с невалидна дата."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Този сертификат е невалиден."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Неизвестна грешка в сертификата."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Този сертификат не е от надежден орган."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Името на сайта не съответства на името в сертификата."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Този сертификат е изтекъл."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Този сертификат още не е валиден."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Този сертификат е с невалидна дата."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Този сертификат е невалиден."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Неизвестна грешка в сертификата."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Предупреждение относно сигурността"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Преглед на сертификата"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Адрес:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Данни за страницата"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-bn/strings.xml b/packages/CaptivePortalLogin/res/values-bn/strings.xml
index fb703cf..3fbe2f2 100644
--- a/packages/CaptivePortalLogin/res/values-bn/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-bn/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"আপনি যে নেটওয়ার্কে যোগ দেওয়ার চেষ্টা করছেন তাতে নিরাপত্তার সমস্যা আছে।"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"উদাহরণস্বরূপ, লগ-ইন পৃষ্ঠাটি প্রদর্শিত প্রতিষ্ঠানের অন্তর্গত নাও হতে পারে৷"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"যাই হোক না কেন ব্রাউজারের মাধ্যমে অবিরত রাখুন"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Sideinfo"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sikkerhetsadvarsel"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vis sertifikat"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sertifikatet er ikke fra en pålitelig myndighet."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Navnet på nettstedet samsvarer ikke med navnet på sertifikatet."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Sertifikatet er utløpt."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sertifikatet er ikke gyldig ennå."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dette sertifikatet har en ugyldig dato."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Dette sertifikatet er ugyldig."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Ukjent sertifikatfeil."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"এই সার্টিফিকেটটি একটি বিশ্বস্ত কর্তৃপক্ষের তরফ থেকে নয়।"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"সাইটের নামটি সার্টিফিকেটে লেখা নামের সাথে মিলছে না।"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"এই সার্টিফিকেটের মেয়াদ শেষ হয়ে গেছে।"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"সার্টিফিকেটটি এখনও সঠিক নয়।"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"এই সার্টিফিকেটের তারিখটি সঠিক নয়।"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"সার্টিফিকেটটি সঠিক নয়।"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"সার্টিফিকেটের সমস্যাটি অজানা।"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"নিরাপত্তার সতর্কতা"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"সার্টিফিকেট দেখুন"</string>
+    <string name="ok" msgid="2817931639040794018">"ঠিক আছে"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"ঠিকানা:"</string>
+    <string name="page_info" msgid="4416941086705172545">"পৃষ্ঠার তথ্য"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-bs/strings.xml b/packages/CaptivePortalLogin/res/values-bs/strings.xml
index 10be0e5..60c153a 100644
--- a/packages/CaptivePortalLogin/res/values-bs/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-bs/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Mreža kojoj pokušavate pristupiti ima sigurnosnih problema."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Naprimjer, stranica za prijavu možda ne pripada prikazanoj organizaciji."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Ipak nastavi preko preglednika"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Ova potvrda ne potiče iz pouzdanog izvora."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Naziv web lokacije se ne podudara s nazivom na potvrdi."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Ova potvrda je istekla."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Ova potvrda još uvijek nije važeća."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Ova potvrda sadrži nevažeći datum."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Ova potvrda je nevažeća."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Nepoznata greška potvrde."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Sigurnosno upozorenje"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Prikaži potvrdu"</string>
+    <string name="ok" msgid="2817931639040794018">"UREDU"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adresa:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informacije o stranici"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ca/strings.xml b/packages/CaptivePortalLogin/res/values-ca/strings.xml
index a2c9ed8..557c3f4 100644
--- a/packages/CaptivePortalLogin/res/values-ca/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ca/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"La xarxa a què et vols connectar té problemes de seguretat."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Per exemple, la pàgina d\'inici de sessió podria no pertànyer a l\'organització que es mostra."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continua igualment mitjançant el navegador"</string>
-    <string name="ok" msgid="1509280796718850364">"D\'acord"</string>
-    <string name="page_info" msgid="4048529256302257195">"Informació de la pàgina"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adreça:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Advertiment de seguretat"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visualitza el certificat"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Aquest certificat no és d\'una autoritat de confiança."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"El nom del lloc no coincideix amb el del certificat."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Aquest certificat ha caducat."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Aquest certificat encara no és vàlid."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Aquest certificat té una data no vàlida."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Aquest certificat no és vàlid."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Error de certificat desconegut."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Aquest certificat no és d\'una autoritat de confiança."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"El nom del lloc web no coincideix amb el que inclou el certificat."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Aquest certificat ha caducat."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Aquest certificat encara no és vàlid."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Aquest certificat té una data no vàlida."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Aquest certificat no és vàlid."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"S\'ha produït un error desconegut de certificat."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Advertiment de seguretat"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Mostra el certificat"</string>
+    <string name="ok" msgid="2817931639040794018">"D\'acord"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adreça:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informació de la pàgina"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-cs/strings.xml b/packages/CaptivePortalLogin/res/values-cs/strings.xml
index be649a5..0328c76 100644
--- a/packages/CaptivePortalLogin/res/values-cs/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-cs/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Síť, ke které se pokoušíte připojit, má bezpečnostní problémy."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Například přihlašovací stránka nemusí patřit do zobrazované organizace."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Přesto pokračovat prostřednictvím prohlížeče"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Informace o stránce"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adresa:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Upozornění zabezpečení"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Zobrazit certifikát"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Tento certifikát nepochází od důvěryhodné autority."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Název webu se neshoduje s názvem uvedeným v certifikátu."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Platnost certifikátu vypršela."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Tento certifikát ještě není platný."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Datum tohoto certifikátu není platné."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Tento certifikát je neplatný."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Neznámá chyba certifikátu."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Tento certifikát nepochází od důvěryhodné autority."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Název webu se neshoduje s názvem uvedeným v certifikátu."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Platnost certifikátu vypršela."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Tento certifikát ještě není platný."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Datum tohoto certifikátu není platné."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Tento certifikát je neplatný."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Neznámá chyba certifikátu."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Bezpečnostní upozornění"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Zobrazit certifikát"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adresa:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informace o stránce"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-da/strings.xml b/packages/CaptivePortalLogin/res/values-da/strings.xml
index 8183105..b9cf7fe9 100644
--- a/packages/CaptivePortalLogin/res/values-da/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-da/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Der er sikkerhedsproblemer på det netværk, du forsøger at logge ind på."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Det er f.eks. ikke sikkert, at loginsiden tilhører den anførte organisation."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Fortsæt alligevel via browseren"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Sideoplysninger"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sikkerhedsadvarsel"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vis certifikat"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Dette certifikat stammer ikke fra en troværdig autoritet."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Navnet på websitet stemmer ikke overens med navnet på certifikatet."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Dette certifikat er udløbet."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Dette certifikat er endnu ikke gyldigt."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dette certifikat har en ugyldig dato."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Dette certifikat er ugyldigt."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Ukendt fejl i certifikatet."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Dette certifikat stammer ikke fra en pålidelig kilde."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Navnet på websitet stemmer ikke overens med navnet på certifikatet."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Dette certifikat er udløbet."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Dette certifikat er ikke gyldigt endnu."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Dette certifikat har en ugyldig dato."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Dette certifikat er ugyldigt."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Ukendt certifikatfejl."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Sikkerhedsadvarsel"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Se certifikat"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adresse:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Sideoplysninger"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-de/strings.xml b/packages/CaptivePortalLogin/res/values-de/strings.xml
index a9b7415..bca956e 100644
--- a/packages/CaptivePortalLogin/res/values-de/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-de/strings.xml
@@ -2,23 +2,23 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="5934709770924185752">"CaptivePortalLogin"</string>
-    <string name="action_use_network" msgid="6076184727448466030">"Dieses Netzwerk im Istzustand verwenden"</string>
-    <string name="action_do_not_use_network" msgid="4577366536956516683">"Dieses Netzwerk nicht verwenden"</string>
+    <string name="action_use_network" msgid="6076184727448466030">"Netzwerk im Istzustand verwenden"</string>
+    <string name="action_do_not_use_network" msgid="4577366536956516683">"Netzwerk nicht verwenden"</string>
     <string name="action_bar_label" msgid="917235635415966620">"Im Netzwerk anmelden"</string>
     <string name="action_bar_title" msgid="5645564790486983117">"In %1$s anmelden"</string>
     <string name="ssl_error_warning" msgid="6653188881418638872">"Im Netzwerk, zu dem du eine Verbindung herstellen möchtest, liegen Sicherheitsprobleme vor."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Beispiel: Die Log-in-Seite gehört eventuell nicht zur angezeigten Organisation."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Trotzdem in einem Browser fortfahren"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Seiteninfo"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sicherheitswarnung"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Zertifikat ansehen"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Dieses Zertifikat wurde nicht von einer vertrauenswürdigen Stelle ausgegeben."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Name der Website stimmt nicht mit dem Namen auf dem Zertifikat überein."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Dieses Zertifikat ist abgelaufen."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Dieses Zertifikat ist noch nicht gültig."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dieses Zertifikat weist ein ungültiges Datum auf."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Dieses Zertifikat ist ungültig."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Unbekannter Zertifikatfehler"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Dieses Zertifikat stammt nicht von einer vertrauenswürdigen Stelle."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Der Name der Website stimmt nicht mit dem Namen auf dem Zertifikat überein."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Dieses Zertifikat ist abgelaufen."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Dieses Zertifikat ist noch nicht gültig."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Dieses Zertifikat hat ein ungültiges Datum."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Dieses Zertifikat ist ungültig."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Unbekannter Zertifikatfehler."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Sicherheitswarnung"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Zertifikat ansehen"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adresse:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Seiteninformationen"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-el/strings.xml b/packages/CaptivePortalLogin/res/values-el/strings.xml
index 16bf6e2..f4de7c3 100644
--- a/packages/CaptivePortalLogin/res/values-el/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-el/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Παρουσιάζονται προβλήματα ασφάλειας στο δίκτυο στο οποίο προσπαθείτε να συνδεθείτε."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Για παράδειγμα, η σελίδα σύνδεσης ενδέχεται να μην ανήκει στον οργανισμό που εμφανίζεται."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Συνέχεια ούτως ή άλλως μέσω του προγράμματος περιήγησης"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Πληροφορίες σελίδας"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Διεύθυνση:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Προειδοποίηση ασφαλείας"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Προβολή πιστοποιητικού"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Αυτό το πιστοποιητικό δεν προέρχεται από αξιόπιστη αρχή."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Το όνομα του ιστότοπου δεν αντιστοιχεί με το όνομα στο πιστοποιητικό."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Αυτό το πιστοποιητικό έχει λήξει."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Αυτό το πιστοποιητικό δεν είναι έγκυρο ακόμα."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Αυτό το πιστοποιητικό δεν έχει έγκυρη ημερομηνία."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Αυτό το πιστοποιητικό δεν είναι έγκυρο."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Άγνωστο σφάλμα πιστοποιητικού."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Αυτό το πιστοποιητικό δεν προέρχεται από αξιόπιστη αρχή."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Το όνομα του ιστοτόπου δεν αντιστοιχεί στο όνομα στο πιστοποιητικό."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Αυτό το πιστοποιητικό έχει λήξει."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Αυτό το πιστοποιητικό δεν είναι έγκυρο ακόμα."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Αυτό το πιστοποιητικό δεν έχει έγκυρη ημερομηνία."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Αυτό το πιστοποιητικό δεν είναι έγκυρο."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Άγνωστο σφάλμα πιστοποιητικού."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Προειδοποίηση ασφαλείας"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Προβολή πιστοποιητικού"</string>
+    <string name="ok" msgid="2817931639040794018">"ΟΚ"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Διεύθυνση:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Πληροφορίες σελίδας"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-en-rAU/strings.xml b/packages/CaptivePortalLogin/res/values-en-rAU/strings.xml
index 2e8d1f0..9763339 100644
--- a/packages/CaptivePortalLogin/res/values-en-rAU/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rAU/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"The network that you’re trying to join has security issues."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"For example, the login page might not belong to the organisation shown."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continue anyway via browser"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"This certificate isn\'t from a trusted authority."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"The name of the site doesn\'t match the name on the certificate."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"This certificate has expired."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"This certificate isn\'t valid yet."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"This certificate has an invalid date."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"This certificate is invalid."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Unknown certificate error."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Security warning"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"View certificate"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Address:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Page info"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-en-rCA/strings.xml b/packages/CaptivePortalLogin/res/values-en-rCA/strings.xml
index 2e8d1f0..9763339 100644
--- a/packages/CaptivePortalLogin/res/values-en-rCA/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rCA/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"The network that you’re trying to join has security issues."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"For example, the login page might not belong to the organisation shown."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continue anyway via browser"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"This certificate isn\'t from a trusted authority."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"The name of the site doesn\'t match the name on the certificate."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"This certificate has expired."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"This certificate isn\'t valid yet."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"This certificate has an invalid date."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"This certificate is invalid."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Unknown certificate error."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Security warning"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"View certificate"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Address:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Page info"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml b/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
index f940299..9763339 100644
--- a/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"The network that you’re trying to join has security issues."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"For example, the login page might not belong to the organisation shown."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continue anyway via browser"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Page info"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Address:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Security warning"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"View certificate"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"This certificate isn\'t from a trusted authority."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"The name of the site doesn\'t match the name on the certificate."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"This certificate has expired."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"This certificate isn\'t valid yet."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"This certificate has an invalid date."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"This certificate is invalid."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Unknown certificate error."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"This certificate isn\'t from a trusted authority."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"The name of the site doesn\'t match the name on the certificate."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"This certificate has expired."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"This certificate isn\'t valid yet."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"This certificate has an invalid date."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"This certificate is invalid."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Unknown certificate error."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Security warning"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"View certificate"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Address:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Page info"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml b/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
index f940299..9763339 100644
--- a/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"The network that you’re trying to join has security issues."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"For example, the login page might not belong to the organisation shown."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continue anyway via browser"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Page info"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Address:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Security warning"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"View certificate"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"This certificate isn\'t from a trusted authority."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"The name of the site doesn\'t match the name on the certificate."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"This certificate has expired."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"This certificate isn\'t valid yet."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"This certificate has an invalid date."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"This certificate is invalid."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Unknown certificate error."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"This certificate isn\'t from a trusted authority."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"The name of the site doesn\'t match the name on the certificate."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"This certificate has expired."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"This certificate isn\'t valid yet."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"This certificate has an invalid date."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"This certificate is invalid."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Unknown certificate error."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Security warning"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"View certificate"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Address:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Page info"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-en-rXC/strings.xml b/packages/CaptivePortalLogin/res/values-en-rXC/strings.xml
index 9a2051f..b9cc419 100644
--- a/packages/CaptivePortalLogin/res/values-en-rXC/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rXC/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‎‎‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‎‎‏‎‎‎‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‎‎The network you’re trying to join has security issues.‎‏‎‎‏‎"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‎‎‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‏‏‎‏‎‎‎For example, the login page may not belong to the organization shown.‎‏‎‎‏‎"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎‏‏‎‎‎‎‎‎‎‎‏‏‏‎‏‏‎‎‎‏‏‏‎‎‏‎‎‎‏‎‏‎‏‎‏‏‎‎Continue anyway via browser‎‏‎‎‏‎"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‏‏‎‏‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎This certificate isn\'t from a trusted authority.‎‏‎‎‏‎"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎The name of the site doesn\'t match the name on the certificate.‎‏‎‎‏‎"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‏‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‏‏‎‏‏‏‏‏‎This certificate has expired.‎‏‎‎‏‎"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‏‎‎‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‏‎‎‎‎‎‏‏‏‎‎‎‎‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‎This certificate isn\'t valid yet.‎‏‎‎‏‎"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‏‏‏‎This certificate has an invalid date.‎‏‎‎‏‎"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‎This certificate is invalid.‎‏‎‎‏‎"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎‏‏‎‏‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎Unknown certificate error.‎‏‎‎‏‎"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‎‎‎‎‏‏‎‏‎‎‎‎‎‎‎‎‎‏‎‏‏‎‎‎‎‏‎‏‎‎‎Security warning‎‏‎‎‏‎"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎View certificate‎‏‎‎‏‎"</string>
+    <string name="ok" msgid="2817931639040794018">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‎‎‎‏‎‏‏‏‎‏‏‎‏‎‎‎‏‎‎OK‎‏‎‎‏‎"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‎‏‎‏‎‏‎‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‎‏‎‏‏‎Address:‎‏‎‎‏‎"</string>
+    <string name="page_info" msgid="4416941086705172545">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‎‎‎‎‎‎‏‎‎‎‎‎‏‎Page info‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml b/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml
index c011664..d7ddaa7 100644
--- a/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"La red a la que intentas conectarte tiene problemas de seguridad."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Por ejemplo, es posible que la página de acceso no pertenezca a la organización que aparece."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuar de todos modos desde el navegador"</string>
-    <string name="ok" msgid="1509280796718850364">"Aceptar"</string>
-    <string name="page_info" msgid="4048529256302257195">"Información de la página"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Dirección:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Advertencia de seguridad"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Ver certificado"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado no proviene de una autoridad confiable."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"El nombre del sitio no coincide con el nombre del certificado."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado ha expirado."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado aún no es válido."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"La fecha de este certificado no es válida."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado no es válido."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Error de certificado desconocido"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Este certificado no proviene de una autoridad confiable."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"El nombre del sitio no coincide con el nombre del certificado."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Este certificado venció."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Este certificado aún no es válido."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"La fecha de este certificado no es válida."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Este certificado no es válido."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Error de certificado desconocido"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Advertencia de seguridad"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Ver certificado"</string>
+    <string name="ok" msgid="2817931639040794018">"Aceptar"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Dirección:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Información de la página"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-es/strings.xml b/packages/CaptivePortalLogin/res/values-es/strings.xml
index 65244e7..e10380f 100644
--- a/packages/CaptivePortalLogin/res/values-es/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-es/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"La red a la que intentas unirte tiene problemas de seguridad."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Por ejemplo, es posible que la página de inicio de sesión no pertenezca a la organización mostrada."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuar de todos modos a través del navegador"</string>
-    <string name="ok" msgid="1509280796718850364">"Aceptar"</string>
-    <string name="page_info" msgid="4048529256302257195">"Información de la página"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Dirección:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Advertencia de seguridad"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Ver certificado"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado no procede de una entidad de certificación de confianza."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"El nombre del sitio no coincide con el del certificado."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado ha caducado."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado aún no es válido."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"La fecha de este certificado no es válida."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado no es válido."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Error de certificado desconocido"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Este certificado no procede de una entidad de confianza."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"El nombre del sitio web no coincide con el del certificado."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Este certificado ha caducado."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Este certificado aún no es válido."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"La fecha de este certificado no es válida."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Este certificado no es válido."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Error de certificado desconocido."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Advertencia de seguridad"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Ver certificado"</string>
+    <string name="ok" msgid="2817931639040794018">"Aceptar"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Dirección:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Información de la página"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-et/strings.xml b/packages/CaptivePortalLogin/res/values-et/strings.xml
index e4c4c98..2894383 100644
--- a/packages/CaptivePortalLogin/res/values-et/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-et/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Võrgul, millega üritate ühenduse luua, on turvaprobleeme."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Näiteks ei pruugi sisselogimisleht kuuluda kuvatavale organisatsioonile."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Jätka siiski brauseris"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Lehe teave"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Aadress:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Turvahoiatus"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Kuva sertifikaat"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"See sertifikaat ei pärine usaldusväärselt asutuselt."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Saidi nimi ei vasta sertifikaadil olevale nimele."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"See sertifikaat on aegunud."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"See sertifikaat pole veel kehtiv."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Sellel sertifikaadil on kehtetu kuupäev."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"See sertifikaat on kehtetu."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Tundmatu sertifikaadiviga."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"See sertifikaat ei pärine usaldusväärselt asutuselt."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Saidi nimi ei vasta sertifikaadil olevale nimele."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"See sertifikaat on aegunud."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"See sertifikaat pole veel kehtiv."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Sellel sertifikaadil on kehtetu kuupäev."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"See sertifikaat on kehtetu."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Tundmatu sertifikaadiviga."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Turvahoiatus"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Kuva sertifikaat"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Aadress:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Lehe teave"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-eu/strings.xml b/packages/CaptivePortalLogin/res/values-eu/strings.xml
index 8925aac..b7233ab 100644
--- a/packages/CaptivePortalLogin/res/values-eu/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-eu/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Erabili nahi duzun sareak segurtasun-arazoak ditu."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Adibidez, baliteke saioa hasteko orria adierazitako erakundearena ez izatea."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Jarraitu arakatzailearen bidez, halere"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Ziurtagiria ez da autoritate fidagarri batena."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Webgunearen izena ez dator bat ziurtagirian agertzen den izenarekin."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Ziurtagiria iraungi da."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Ziurtagiriak ez du balio oraindik."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Ziurtagiriaren datak ez du balio."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Ziurtagiriak ez du balio."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Errore ezezagun bat gertatu da ziurtagiriarekin."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Segurtasun-abisua"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Ikusi ziurtagiria"</string>
+    <string name="ok" msgid="2817931639040794018">"Ados"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Helbidea:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Orriari buruzko informazioa"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-fa/strings.xml b/packages/CaptivePortalLogin/res/values-fa/strings.xml
index 27b9b7f..db9f7e8 100644
--- a/packages/CaptivePortalLogin/res/values-fa/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-fa/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"شبکه‌ای که می‌خواهید به آن بپیوندید مشکلات امنیتی دارد."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"به عنوان مثال، صفحه ورود به سیستم ممکن است متعلق به سازمان نشان داده شده نباشد."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"در هر صورت از طریق مرورگر ادامه یابد"</string>
-    <string name="ok" msgid="1509280796718850364">"تأیید"</string>
-    <string name="page_info" msgid="4048529256302257195">"اطلاعات صفحه"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"آدرس:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"اخطار امنیتی"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"مشاهده گواهی"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"این گواهی از یک منبع مورد اطمینان صادر نشده است."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"نام سایت با نام موجود در گواهی مطابقت ندارد."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"این گواهی منقضی شده است."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"این گواهی هنوز معتبر نیست."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"تاریخ این گواهی نامعتبر است."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"این گواهی نامعتبر است."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"خطای ناشناخته در گواهی."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"این گواهی از یک منبع مورد‌اطمینان صادر نشده است."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"نام سایت با نام موجود در گواهی مطابقت ندارد."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"این گواهی منقضی شده است."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"این گواهی هنوز معتبر نیست."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"تاریخ این گواهی نامعتبر است."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"این گواهی نامعتبر است."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"خطای ناشناخته در گواهی."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"اخطار امنیتی"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"مشاهده گواهی"</string>
+    <string name="ok" msgid="2817931639040794018">"تأیید"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"نشانی:"</string>
+    <string name="page_info" msgid="4416941086705172545">"اطلاعات صفحه"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-fi/strings.xml b/packages/CaptivePortalLogin/res/values-fi/strings.xml
index 8086fbf..1d7fcb0 100644
--- a/packages/CaptivePortalLogin/res/values-fi/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-fi/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Verkossa, johon yrität muodostaa yhteyttä, on turvallisuusongelmia."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Kirjautumissivu ei välttämättä kuulu näytetylle organisaatiolle."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Jatka silti selaimen kautta."</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Sivun tiedot"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Osoite:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Suojausvaroitus"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Näytä varmenne"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Varmenteen myöntäjä ei ole luotettava taho."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Sivuston nimi ei vastaa varmenteessa olevaa nimeä."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Varmenne ei ole enää voimassa."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Varmenne ei ole vielä voimassa."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Varmenteen päiväys ei kelpaa."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Varmenne on virheellinen."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Tuntematon varmennevirhe."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Varmenteen myöntäjä ei ole luotettava taho."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Sivuston nimi ei vastaa varmenteessa olevaa nimeä."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Varmenne ei ole enää voimassa."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Varmenne ei ole vielä voimassa."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Varmenteen päiväys ei kelpaa."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Varmenne on virheellinen."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Tuntematon varmennevirhe."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Suojausvaroitus"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Näytä varmenne"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Osoite:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Sivun tiedot"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-fr-rCA/strings.xml b/packages/CaptivePortalLogin/res/values-fr-rCA/strings.xml
index a7525a5..979e236 100644
--- a/packages/CaptivePortalLogin/res/values-fr-rCA/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-fr-rCA/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Le réseau que vous essayez de rejoindre présente des problèmes de sécurité."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Par exemple, la page de connexion pourrait ne pas appartenir à l\'organisation représentée."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuer quand même dans un navigateur"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Ce certificat ne provient pas d\'une autorité de confiance."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Le nom du site ne correspond pas au nom figurant sur le certificat."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Ce certificat a expiré."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Ce certificat n\'est pas encore valide."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Ce certificat contient une date non valide."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Ce certificat n\'est pas valide."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Erreur de certificat inconnue."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Avertissement de sécurité"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Afficher le certificat"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adresse :"</string>
+    <string name="page_info" msgid="4416941086705172545">"Renseignements sur la page"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-fr/strings.xml b/packages/CaptivePortalLogin/res/values-fr/strings.xml
index 39fc569..e348a4d 100644
--- a/packages/CaptivePortalLogin/res/values-fr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-fr/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Le réseau que vous essayez de rejoindre présente des problèmes de sécurité."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Par exemple, la page de connexion peut ne pas appartenir à l\'organisation représentée."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuer quand même dans le navigateur"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Infos sur la page"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adresse :"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Avertissement de sécurité"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Afficher le certificat"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ce certificat provient d\'une autorité non approuvée."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Le nom du site ne correspond pas au nom indiqué dans le certificat."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Le certificat a expiré."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Ce certificat n\'est pas encore valide."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"La date de ce certificat n\'est pas valide."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Ce certificat n\'est pas valide."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Erreur : Certificat inconnu."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Ce certificat provient d\'une autorité non approuvée."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Le nom du site ne correspond pas au nom indiqué dans le certificat."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Ce certificat a expiré."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Ce certificat n\'est pas encore valide."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"La date de ce certificat n\'est pas valide."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Ce certificat n\'est pas valide."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Erreur de certificat inconnue."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Avertissement de sécurité"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Afficher le certificat"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adresse :"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informations sur la page"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-gl/strings.xml b/packages/CaptivePortalLogin/res/values-gl/strings.xml
index 6578285..6419516 100644
--- a/packages/CaptivePortalLogin/res/values-gl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-gl/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"A rede á que tentas unirte ten problemas de seguranza."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Por exemplo, é posible que a páxina de inicio de sesión non pertenza á organización que se mostra."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuar igualmente co navegador"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Este certificado non procede dunha autoridade de confianza."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"O nome do sitio non coincide co nome que aparece no certificado."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Este certificado caducou."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Este certificado aínda non é válido."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Este certificado ten unha data non válida."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Este certificado non é válido."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Produciuse un erro descoñecido relacionado co certificado."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Advertencia de seguranza"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Ver certificado"</string>
+    <string name="ok" msgid="2817931639040794018">"Aceptar"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Enderezo:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Información da páxina"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-gu/strings.xml b/packages/CaptivePortalLogin/res/values-gu/strings.xml
index c15eca4..aef043f 100644
--- a/packages/CaptivePortalLogin/res/values-gu/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-gu/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"તમે જોડાવાનો પ્રયાસ કરી રહ્યાં છો તે નેટવર્કમાં સુરક્ષા સમસ્યાઓ છે."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"ઉદાહરણ તરીકે, લોગિન પૃષ્ઠ દર્શાવેલ સંસ્થાનું હોઈ શકતું નથી."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"બ્રાઉઝર મારફતે કોઈપણ રીતે ચાલુ રાખો"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"આ પ્રમાણપત્ર વિશ્વસનીય સત્તાધિકારી તરફથી મળ્યું નથી."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"સાઇટનું નામ એ પ્રમાણપત્ર પર રહેલાં નામ સાથે મેળ ખાતું નથી."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"આ પ્રમાણપત્રની સમયસીમા સમાપ્ત થઈ ગઈ છે."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"આ પ્રમાણપત્ર હજુ માન્ય નથી."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"આ પ્રમાણપત્રમાં અમાન્ય તારીખ છે."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"આ પ્રમાણપત્ર અમાન્ય છે."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"પ્રમાણપત્રમાં અજાણી ભૂલ."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"સુરક્ષા વિશે ચેતવણી"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"પ્રમાણપત્ર જુઓ"</string>
+    <string name="ok" msgid="2817931639040794018">"ઓકે"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"સરનામું:"</string>
+    <string name="page_info" msgid="4416941086705172545">"પેજ વિશે માહિતી"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-hi/strings.xml b/packages/CaptivePortalLogin/res/values-hi/strings.xml
index d924fff..b8ae82a 100644
--- a/packages/CaptivePortalLogin/res/values-hi/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hi/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"आप जिस नेटवर्क में शामिल होने का प्रयास कर रहे हैं उसमें सुरक्षा समस्‍याएं हैं."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"उदाहरण के लिए, हो सकता है कि लॉगिन पृष्‍ठ दिखाए गए संगठन से संबद्ध ना हो."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ब्राउज़र के द्वारा फिर जारी रखें"</string>
-    <string name="ok" msgid="1509280796718850364">"ठीक"</string>
-    <string name="page_info" msgid="4048529256302257195">"पृष्ठ जानकारी"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"पता:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"सुरक्षा चेतावनी"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"प्रमाणपत्र देखें"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"यह प्रमाणपत्र किसी विश्वस्त प्राधिकारी का नहीं है."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"साइट का नाम, प्रमाणपत्र के नाम से मिलान नहीं करता."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"इस प्रमाणपत्र की समय सीमा समाप्त हो गई है."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"यह प्रमाणपत्र अभी तक मान्य नहीं है."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"इस प्रमाणपत्र में एक अमान्‍य दिनांक है."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"यह प्रमाणपत्र अमान्य है."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"अज्ञात प्रमाणपत्र त्रुटि."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"यह प्रमाणपत्र किसी भरोसेमंद अधिकारी का नहीं है."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"साइट के नाम का मिलान प्रमाणपत्र में दिए नाम से नहीं हो रहा है."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"इस प्रमाणपत्र की समय-सीमा खत्म हो चुकी है."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"यह प्रमाणपत्र अभी तक मान्य नहीं है."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"इस प्रमाणपत्र की तारीख गलत है."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"यह प्रमाणपत्र अमान्य है."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"प्रमाणपत्र में अनजान गड़बड़ी."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"सुरक्षा चेतावनी"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"प्रमाणपत्र देखें"</string>
+    <string name="ok" msgid="2817931639040794018">"ठीक है"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"पता:"</string>
+    <string name="page_info" msgid="4416941086705172545">"पेज की जानकारी"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-hr/strings.xml b/packages/CaptivePortalLogin/res/values-hr/strings.xml
index 11b1dd3..f6adcdb 100644
--- a/packages/CaptivePortalLogin/res/values-hr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hr/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Mreža kojoj se pokušavate pridružiti ima sigurnosne poteškoće."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Na primjer, stranica za prijavu možda ne pripada prikazanoj organizaciji."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Ipak nastavi putem preglednika"</string>
-    <string name="ok" msgid="1509280796718850364">"U redu"</string>
-    <string name="page_info" msgid="4048529256302257195">"Informacije o stranici"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adresa:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Upozorenje o sigurnosti"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Prikaži certifikat"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ovaj certifikat ne potječe iz pouzdanog izvora."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Naziv web-lokacije ne podudara se s nazivom na certifikatu."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Ovaj je certifikat istekao."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Ovaj certifikat još nije važeći."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Ovaj certifikat ima nevažeći datum."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Ovaj certifikat nije valjan."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Nepoznata pogreška certifikata."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Ovaj certifikat ne potječe iz pouzdanog izvora."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Naziv web-lokacije ne podudara se s nazivom na certifikatu."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Ovaj je certifikat istekao."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Ovaj certifikat još nije važeći."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Ovaj certifikat ima nevažeći datum."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Ovaj certifikat nije važeći."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Nepoznata pogreška certifikata."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Sigurnosno upozorenje"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Pregledajte certifikat"</string>
+    <string name="ok" msgid="2817931639040794018">"U redu"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adresa:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informacije o stranici"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-hu/strings.xml b/packages/CaptivePortalLogin/res/values-hu/strings.xml
index 145e2ab..ab289d1 100644
--- a/packages/CaptivePortalLogin/res/values-hu/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hu/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Biztonsági problémák vannak azzal a hálózattal, amelyhez csatlakozni szeretne."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Például lehet, hogy a bejelentkezési oldal nem a megjelenített szervezethez tartozik."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Folytatás ennek ellenére böngészőn keresztül"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Oldaladatok"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Cím:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Biztonsági figyelmeztetés"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Tanúsítvány megtekintése"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ez a tanúsítvány nem hiteles tanúsítványkibocsátótól származik."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"A webhely neve nem egyezik a tanúsítványon lévő névvel."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"A tanúsítvány lejárt."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"A tanúsítvány még nem érvényes."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"A tanúsítvány dátuma érvénytelen."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Ez a tanúsítvány érvénytelen."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Ismeretlen tanúsítványhiba."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Ez a tanúsítvány nem hiteles tanúsítványkibocsátótól származik."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"A webhely neve nem egyezik a tanúsítványon lévő névvel."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"A tanúsítvány lejárt."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"A tanúsítvány még nem érvényes."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"A tanúsítvány dátuma érvénytelen."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Ez a tanúsítvány érvénytelen."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Ismeretlen tanúsítványhiba."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Biztonsági figyelmeztetés"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Tanúsítvány megtekintése"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Cím:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Oldaladatok"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-hy/strings.xml b/packages/CaptivePortalLogin/res/values-hy/strings.xml
index a0ee862..d859d90 100644
--- a/packages/CaptivePortalLogin/res/values-hy/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hy/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Ցանցը, որին փորձում եք միանալ, անվտանգության խնդիրներ ունի:"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Օրինակ՝ մուտքի էջը կարող է ցուցադրված կազմակերպության էջը չլինել:"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Շարունակել այնուամենայնիվ դիտարկիչի միջոցով"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Հավաստագրի աղբյուրը վստահելի չէ:"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Կայքի անունը չի համապատասխանում հավաստագրում նշված անվանը:"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Հավաստագրի ժամկետը լրացել է:"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Հավաստագիրը դեռ վավեր չէ:"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Հավաստագրի ամսաթիվն անվավեր է:"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Հավաստագիրն անվավեր է:"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Հավաստագրի հետ կապված անհայտ սխալ առաջացավ:"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Զգուշացում"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Դիտել հավաստագիրը"</string>
+    <string name="ok" msgid="2817931639040794018">"Եղավ"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Հասցե՝"</string>
+    <string name="page_info" msgid="4416941086705172545">"Էջի մասին"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-in/strings.xml b/packages/CaptivePortalLogin/res/values-in/strings.xml
index 4a335dd..7036318 100644
--- a/packages/CaptivePortalLogin/res/values-in/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-in/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Jaringan yang ingin Anda masuki mengalami masalah keamanan."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Misalnya, halaman masuk mungkin bukan milik organisasi yang ditampilkan."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Tetap lanjutkan melalui browser"</string>
-    <string name="ok" msgid="1509280796718850364">"Oke"</string>
-    <string name="page_info" msgid="4048529256302257195">"Info laman"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Alamat:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Peringatan sertifikat"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Lihat sertifikat"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sertifikat ini tidak berasal dari otoritas tepercaya."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Nama situs tidak cocok dengan nama pada sertifikat."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Sertifikat ini telah kedaluwarsa."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sertifikat ini belum valid."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Tanggal sertifikat ini tidak valid."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Sertifikat ini tidak valid."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Kesalahan sertifikat tak dikenal."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Sertifikat ini tidak berasal dari otoritas tepercaya."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Nama situs tidak cocok dengan nama pada sertifikat."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Masa berlaku sertifikat ini telah berakhir."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Sertifikat ini belum valid."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Tanggal sertifikat ini tidak valid."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Sertifikat ini tidak valid."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Error sertifikat tak dikenal."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Peringatan keamanan"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Lihat sertifikat"</string>
+    <string name="ok" msgid="2817931639040794018">"Oke"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Alamat:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Info halaman"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-is/strings.xml b/packages/CaptivePortalLogin/res/values-is/strings.xml
index 8fde24b..7c2a5e4 100644
--- a/packages/CaptivePortalLogin/res/values-is/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-is/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Öryggisvandamál eru á netinu sem þú ert að reyna að tengjast."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Til dæmis getur verið að innskráningarsíðan tilheyri ekki fyrirtækinu sem birtist."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Halda samt áfram í vafra"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Þetta vottorð er ekki frá traustum aðila."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Nafnið á síðunni passar ekki við nafnið á vottorðinu."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Þetta vottorð er útrunnið."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Þetta vottorð hefur ekki enn tekið gildi."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Þetta vottorð er með ógilda dagsetningu."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Þetta vottorð er ógilt."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Óþekkt vottorðsvilla."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Öryggisviðvörun"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Skoða vottorð"</string>
+    <string name="ok" msgid="2817931639040794018">"Í lagi"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Netfang:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Upplýsingar um síðu"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-it/strings.xml b/packages/CaptivePortalLogin/res/values-it/strings.xml
index 2cc4038..3896cb4 100644
--- a/packages/CaptivePortalLogin/res/values-it/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-it/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"La rete a cui stai tentando di accedere presenta problemi di sicurezza."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Ad esempio, la pagina di accesso potrebbe non appartenere all\'organizzazione indicata."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continua comunque dal browser"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Info pagina"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Indirizzo:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Avviso di sicurezza"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visualizza certificato"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Questo certificato non proviene da un\'autorità attendibile."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Il nome del sito non corrisponde al nome nel certificato."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Il certificato è scaduto."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Questo certificato non è ancora valido."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Questo certificato presenta una data non valida."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Questo certificato non è valido."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Errore certificato sconosciuto."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Questo certificato non proviene da un\'autorità attendibile."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Il nome del sito non corrisponde al nome nel certificato."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Il certificato è scaduto."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Questo certificato non è ancora valido."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Questo certificato presenta una data non valida."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Questo certificato non è valido."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Errore certificato sconosciuto."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Avviso di sicurezza"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Visualizza certificato"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Indirizzo:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informazioni sulla pagina"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-iw/strings.xml b/packages/CaptivePortalLogin/res/values-iw/strings.xml
index 527e692..4ce98ee 100644
--- a/packages/CaptivePortalLogin/res/values-iw/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-iw/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"יש בעיות אבטחה ברשת שאליה אתה מנסה להתחבר."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"לדוגמה, ייתכן שדף ההתחברות אינו שייך לארגון המוצג."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"המשך בכל זאת באמצעות דפדפן"</string>
-    <string name="ok" msgid="1509280796718850364">"אישור"</string>
-    <string name="page_info" msgid="4048529256302257195">"פרטי דף"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"כתובת:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"אזהרת אבטחה"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"הצג אישור"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"אישור זה אינו מגיע מרשות אמינה."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"שם האתר לא תואם לשם באישור."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"פג תוקפו של אישור זה."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"אישור זה אינו חוקי עדיין."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"לאישור זה יש תאריך בלתי חוקי."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"אישור זה אינו חוקי."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"שגיאת אישור לא ידועה."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"אישור זה אינו מגיע מרשות אמינה."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"שם האתר לא תואם לשם באישור."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"פג תוקפו של אישור זה."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"אישור זה אינו חוקי עדיין."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"לאישור זה יש תאריך בלתי חוקי."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"אישור זה אינו חוקי."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"שגיאת אישור לא ידועה."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"אזהרת אבטחה"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"הצגת אישור"</string>
+    <string name="ok" msgid="2817931639040794018">"אישור"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"כתובת:"</string>
+    <string name="page_info" msgid="4416941086705172545">"פרטי דף"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ja/strings.xml b/packages/CaptivePortalLogin/res/values-ja/strings.xml
index bcc8686..bab9026 100644
--- a/packages/CaptivePortalLogin/res/values-ja/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ja/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"接続しようとしているネットワークにセキュリティの問題があります。"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"たとえば、ログインページが表示されている組織に属していない可能性があります。"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ブラウザから続行"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"ページ情報"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"アドレス:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"セキュリティ警告"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"証明書を表示"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"この証明書は信頼できる認証機関のものではありません。"</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"サイト名と証明書上の名前が一致しません。"</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"この証明書は有効期限切れです。"</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"この証明書はまだ有効ではありません。"</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"この証明書の日付は無効です。"</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"この証明書は無効です。"</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"不明な証明書エラーです。"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"この証明書は信頼できる認証機関のものではありません。"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"サイト名と証明書上の名前が一致しません。"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"この証明書は有効期限切れです。"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"この証明書はまだ有効ではありません。"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"この証明書の日付は無効です。"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"この証明書は無効です。"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"不明な証明書エラーです。"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"セキュリティに関する警告"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"証明書を表示"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"メールアドレス:"</string>
+    <string name="page_info" msgid="4416941086705172545">"ページ情報"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ka/strings.xml b/packages/CaptivePortalLogin/res/values-ka/strings.xml
index 1ccff12..ec820e5 100644
--- a/packages/CaptivePortalLogin/res/values-ka/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ka/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"ქსელს, რომელზედაც მიერთებას ცდილობთ, უსაფრთხოების პრობლემები აქვს."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"მაგალითად, სისტემაში შესვლის გვერდი შეიძლება არ ეკუთვნოდეს ნაჩვენებ ორგანიზაციას."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ბრაუზერში გაგრძელება"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"ეს სერტიფიკატი არ არის გაცემული ნდობით აღჭურვილი ორგანოს მიერ."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"საიტის სახელი არ ემთხვევა სერტიფიკატში მითითებულს."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"ეს სერტიფიკატი ვადაგასულია."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"ეს სერტიფიკატი ჯერ არ არის ძალაში."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"ამ სერტიფიკატში მითითებულია არასწორი თარიღი."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"ეს სერტიფიკატი არასწორია."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"წარმოიშვა სერტიფიკატთან დაკავშირებული უცნობი შეცდომა."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"გაფრთხილება უსაფრთხოების შესახებ"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"სერტიფიკატის ნახვა"</string>
+    <string name="ok" msgid="2817931639040794018">"კარგი"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"მისამართი:"</string>
+    <string name="page_info" msgid="4416941086705172545">"გვერდის ინფორმაცია"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-kk/strings.xml b/packages/CaptivePortalLogin/res/values-kk/strings.xml
index a904dea..a23eafd 100644
--- a/packages/CaptivePortalLogin/res/values-kk/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-kk/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Қосылайын деп жатқан желіңіз қауіпсіз болуы мүмкін."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Мысалы, кіру беті көрсетілген ұйымға тиесілі болмауы мүмкін."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Бәрібір браузер арқылы жалғастыру"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Сертификатты сенімді орган бермеген."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Сайттың атауы мен сертификатта көрсетілген атау сәйкес келмейді."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Сертификаттың жарамдылық мерзімі аяқталған."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Сертификат әлі жарамсыз."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Сертификат күні жарамсыз."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Сертификат жарамсыз."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Сертификатқа қатысты белгісіз қате."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Қауіпсіздік туралы ескерту"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Сертификатты көру"</string>
+    <string name="ok" msgid="2817931639040794018">"Жарайды"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Мекенжай:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Бет туралы ақпарат"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-km/strings.xml b/packages/CaptivePortalLogin/res/values-km/strings.xml
index a0497f8..b4274e9 100644
--- a/packages/CaptivePortalLogin/res/values-km/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-km/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"បណ្តាញដែលអ្នកកំពុងព្យាយាមចូលមានបញ្ហាសុវត្ថិភាព។"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"ឧបករណ៍៖ ទំព័រចូលនេះអាចនឹងមិនមែនជាកម្មសិទ្ធិរបស់ស្ថាប័នដែលបានបង្ហាញនេះទេ។"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"យ៉ាងណាក៏ដោយនៅតែបន្តតាមរយៈកម្មវិធីរុករក"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"វិញ្ញាបនបត្រនេះ​មិនបានចេញ​ដោយ​អាជ្ញាធរដែល​គួរ​ឱ្យ​ទុកចិត្ត​ទេ។"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"ឈ្មោះ​គេហទំព័រ​នេះ​មិន​ត្រូវនឹង​ឈ្មោះ​នៅលើវិញ្ញាបនបត្រទេ។"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"វិញ្ញាបនបត្រនេះ​ផុត​កំណត់​ហើយ។"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"វិញ្ញាបនបត្រនេះមិន​ទាន់​មាន​សុពលភាពនៅ​ឡើយ​ទេ។"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"វិញ្ញាបនបត្រនេះ​មាន​កាល​បរិច្ឆេទដែលគ្មាន​សុពលភាព។"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"វិញ្ញាបនបត្រនេះគ្មាន​សុពលភាពទេ។"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"មានបញ្ហា​ដោយសារ​មិនស្គាល់វិញ្ញាបនបត្រ។"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"ការព្រមានផ្នែកសុវត្ថិភាព"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"មើល​វិញ្ញាបនបត្រ"</string>
+    <string name="ok" msgid="2817931639040794018">"យល់ព្រម"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"អាសយដ្ឋាន៖"</string>
+    <string name="page_info" msgid="4416941086705172545">"ព័ត៌មាន​ទំព័រ"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-kn/strings.xml b/packages/CaptivePortalLogin/res/values-kn/strings.xml
index 3084504..731bbcc 100644
--- a/packages/CaptivePortalLogin/res/values-kn/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-kn/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"ನೀವು ಸೇರಬೇಕೆಂದಿರುವ ನೆಟ್‌ವರ್ಕ್ ಭದ್ರತೆ ಸಮಸ್ಯೆಗಳನ್ನು ಹೊಂದಿದೆ."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"ಉದಾಹರಣೆಗೆ, ಲಾಗಿನ್ ಪುಟವು ತೋರಿಸಲಾಗಿರುವ ಸಂಸ್ಥೆಗೆ ಸಂಬಂಧಿಸಿರುವುದಿಲ್ಲ."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ಹೇಗಾದರೂ ಬ್ರೌಸರ್ ಮೂಲಕ ಮುಂದುವರಿಸಿ"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"ಈ ಪ್ರಮಾಣಪತ್ರವು ವಿಶ್ವಾಸಾರ್ಹ ಪ್ರಾಧಿಕಾರದಿಂದ ಬಂದಿಲ್ಲ."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"ಸೈಟ್‌ನ ಹೆಸರು ಪ್ರಮಾಣಪತ್ರದಲ್ಲಿನ ಹೆಸರಿನ ಜೊತೆಗೆ ಹೊಂದಾಣಿಕೆಯಾಗುತ್ತಿಲ್ಲ."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"ಈ ಪ್ರಮಾಣಪತ್ರದ ಅವಧಿ ಮೀರಿದೆ."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"ಈ ಪ್ರಮಾಣಪತ್ರವು ಇನ್ನೂ ಮಾನ್ಯವಾಗಿಲ್ಲ."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"ಈ ಪ್ರಮಾಣಪತ್ರವು ಅಮಾನ್ಯವಾದ ದಿನಾಂಕವನ್ನು ಹೊಂದಿದೆ."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"ಈ ಪ್ರಮಾಣಪತ್ರವು ಅಮಾನ್ಯವಾಗಿದೆ."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"ಪ್ರಮಾಣಪತ್ರದ ಅಜ್ಞಾತ ದೋಷ."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"ಭದ್ರತಾ ಎಚ್ಚರಿಕೆ"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"ಪ್ರಮಾಣಪತ್ರವನ್ನು ವೀಕ್ಷಿಸಿ"</string>
+    <string name="ok" msgid="2817931639040794018">"ಸರಿ"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"ವಿಳಾಸ:"</string>
+    <string name="page_info" msgid="4416941086705172545">"ಪುಟದ ಮಾಹಿತಿ"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ko/strings.xml b/packages/CaptivePortalLogin/res/values-ko/strings.xml
index 7a7f7e0..8c2d9d2 100644
--- a/packages/CaptivePortalLogin/res/values-ko/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ko/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"가입하려는 네트워크에 보안 문제가 있습니다."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"예를 들어 로그인 페이지가 표시된 조직에 속하지 않을 수 있습니다."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"브라우저를 통해 계속하기"</string>
-    <string name="ok" msgid="1509280796718850364">"확인"</string>
-    <string name="page_info" msgid="4048529256302257195">"페이지 정보"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"주소:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"보안 경고"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"인증서 보기"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"신뢰할 수 있는 인증 기관에서 발급한 인증서가 아닙니다."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"사이트 이름이 인증서에 있는 것과 일치하지 않습니다."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"인증서가 만료되었습니다."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"인증서가 아직 유효하지 않습니다."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"인증서 날짜가 유효하지 않습니다."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"인증서가 잘못되었습니다."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"알 수 없는 인증서 오류입니다."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"신뢰할 수 있는 인증 기관에서 발급한 인증서가 아닙니다."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"사이트 이름이 인증서상의 이름과 일치하지 않습니다."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"인증서가 만료되었습니다."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"인증서가 아직 유효하지 않습니다."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"인증서의 날짜가 잘못되었습니다."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"인증서가 잘못되었습니다."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"알 수 없는 인증서 오류입니다."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"보안 경고"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"인증서 보기"</string>
+    <string name="ok" msgid="2817931639040794018">"확인"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"주소:"</string>
+    <string name="page_info" msgid="4416941086705172545">"페이지 정보"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ky/strings.xml b/packages/CaptivePortalLogin/res/values-ky/strings.xml
index af81ce3..6d663cb 100644
--- a/packages/CaptivePortalLogin/res/values-ky/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ky/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Кошулайын деген тармагыңызда коопсуздук көйгөйлөрү бар."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Мисалы, каттоо эсебине кирүү баракчасы көрсөтүлгөн уюмга таандык эмес болушу мүмкүн."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Баары бир серепчи аркылуу улантуу"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Бул тастыктама ишеничтүү мекеме аркылуу берилген эмес."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Сайттын аталышы тастыктаманын аталышына дал келбейт."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Бул тастыктаманын мөөнөтү өтүп кеткен."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Бул тастыктама азырынча жараксыз."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Бул тастыктаманын күнү жараксыз."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Бул тастыктама жараксыз."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Тастыктамага байланыштуу белгисиз ката."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Коопсуздук эскертүүсү"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Тастыктаманы көрүү"</string>
+    <string name="ok" msgid="2817931639040794018">"ЖАРАЙТ"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Дарек:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Барак жөнүндө маалымат"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-lo/strings.xml b/packages/CaptivePortalLogin/res/values-lo/strings.xml
index ee2b263..673bf2c 100644
--- a/packages/CaptivePortalLogin/res/values-lo/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-lo/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"ເຄືອ​ຂ່າຍ​ທີ່​ທ່ານ​ກຳ​ລັງ​ເຂົ້າ​ຮ່ວມ​ມີ​ບັນ​ຫາ​ຄວາມ​ປອດ​ໄພ."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"ຕົວ​ຢ່າງ, ໜ້າ​ລົງ​ຊື່​ເຂົ້າ​ໃຊ້​ອາດ​ຈະ​ບໍ່​ເປັນ​ຂອງ​ອົງ​ການ​ທີ່​ສະ​ແດງ​ຂຶ້ນ."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ແນວ​ໃດ​ກໍ່​ສືບ​ຕໍ່​ຜ່ານບ​ຣາວ​ເຊີ"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"ໃບຮັບຮອງນີ້ບໍ່ໄດ້ມາຈາກໜ່ວຍງານທີ່ເຊື່ອຖືໄດ້."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"ຊື່ຂອງເວັບໄຊບໍ່ກົງກັບຊື່ຢູ່ໃບຮັບຮອງ."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"ໃບຮັບຮອງນີ້ຫມົດອາຍຸແລ້ວ."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"ໃບຮັບຮອງນີ້ບໍ່ຖືກຕ້ອງເທື່ອ."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"ໃບຮັບຮອງນີ້ມີວັນທີບໍ່ຖືກຕ້ອງ."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"ໃບຮັບຮອງນີ້ບໍ່ຖືກຕ້ອງ."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"ໃບຮັບຮອງມີຄວາມຜິດພາດທີ່ບໍ່ຮູ້ຈັກ."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"ຄຳເຕືອນຄວາມປອດໄພ"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"ເບິ່ງໃບຮັບຮອງ"</string>
+    <string name="ok" msgid="2817931639040794018">"ຕົກລົງ"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"ທີ່ຢູ່:"</string>
+    <string name="page_info" msgid="4416941086705172545">"ຂໍ້ມູນໜ້າ"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-lt/strings.xml b/packages/CaptivePortalLogin/res/values-lt/strings.xml
index 158f7ce..eb4c46c 100644
--- a/packages/CaptivePortalLogin/res/values-lt/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-lt/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Kilo tinklo, prie kurio bandote prisijungti, problemų."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Pavyzdžiui, prisijungimo puslapis gali nepriklausyti rodomai organizacijai."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Vis tiek tęsti naudojant naršyklę"</string>
-    <string name="ok" msgid="1509280796718850364">"Gerai"</string>
-    <string name="page_info" msgid="4048529256302257195">"Puslapio informacija"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adresas:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Saugos įspėjimas"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Žiūrėti sertifikatą"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Šį sertifikatą išdavė nepatikima įstaiga."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Svetainės pavadinimas neatitinka sertifikate nurodyto pavadinimo."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Šio sertifikato galiojimo laikas baigėsi."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Šis sertifikatas dar negalioja."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Šio sertifikato data netinkama."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Šis sertifikatas netinkamas."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Nežinoma sertifikato klaida."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Šį sertifikatą išdavė nepatikima įstaiga."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Svetainės pavadinimas neatitinka sertifikate nurodyto pavadinimo."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Šio sertifikato galiojimo laikas baigėsi."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Šis sertifikatas dar negalioja."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Šio sertifikato data netinkama."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Šis sertifikatas netinkamas."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Nežinoma sertifikato klaida."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Saugos įspėjimas"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Žiūrėti sertifikatą"</string>
+    <string name="ok" msgid="2817931639040794018">"Gerai"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adresas"</string>
+    <string name="page_info" msgid="4416941086705172545">"Puslapio informacija"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-lv/strings.xml b/packages/CaptivePortalLogin/res/values-lv/strings.xml
index a42cb22..5554343 100644
--- a/packages/CaptivePortalLogin/res/values-lv/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-lv/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Tīklam, kuram mēģināt pievienoties, ir drošības problēmas."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Piemēram, pieteikšanās lapa, iespējams, nepieder norādītajai organizācijai."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Tik un tā turpināt, izmantojot pārlūkprogrammu"</string>
-    <string name="ok" msgid="1509280796718850364">"Labi"</string>
-    <string name="page_info" msgid="4048529256302257195">"Lapas informācija"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adrese:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Drošības brīdinājums"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Skatīt sertifikātu"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Šo sertifikātu nav izsniegusi uzticama iestāde."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Vietnes nosaukums neatbilst nosaukumam sertifikātā."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Šī sertifikāta derīguma termiņš ir beidzies."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Šis sertifikāts vēl nav derīgs."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Šī sertifikāta datums nav derīgs."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Šis sertifikāts nav derīgs."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Nezināma sertifikāta kļūda."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Šo sertifikātu nav izsniegusi uzticama iestāde."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Vietnes nosaukums neatbilst nosaukumam sertifikātā."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Šī sertifikāta derīguma termiņš ir beidzies."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Šis sertifikāts vēl nav derīgs."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Šī sertifikāta datums nav derīgs."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Šis sertifikāts nav derīgs."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Nezināma sertifikāta kļūda."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Drošības brīdinājums"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Skatīt sertifikātu"</string>
+    <string name="ok" msgid="2817931639040794018">"Labi"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adrese:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Lapas informācija"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-mk/strings.xml b/packages/CaptivePortalLogin/res/values-mk/strings.xml
index 2ae32c8..9a57fca 100644
--- a/packages/CaptivePortalLogin/res/values-mk/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-mk/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Мрежата на која се обидувате да се придружите има проблеми со безбедноста."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"На пример, страницата за најавување може да не припаѓа на организацијата што е прикажана."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Сепак продолжи преку прелистувач"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Сертификатов не е од доверлив орган."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Името на сајтот не се совпаѓа со името на сертификатот."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Сертификатов е истечен."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Сертификатов сѐ уште не е важечки."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Сертификатов има неважечки датум."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Сертификатов е неважечки."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Непозната грешка на сертификатот."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Предупредување за безбедност"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Прикажи го сертификатот"</string>
+    <string name="ok" msgid="2817931639040794018">"Во ред"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Адреса:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Информации за страницата"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ml/strings.xml b/packages/CaptivePortalLogin/res/values-ml/strings.xml
index 79551f8..8fd74d1 100644
--- a/packages/CaptivePortalLogin/res/values-ml/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ml/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"നിങ്ങൾ ചേരാൻ ശ്രമിക്കുന്ന നെറ്റ്‌വർക്കിൽ സുരക്ഷാ പ്രശ്‌നങ്ങളുണ്ടായിരിക്കാം."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"ഉദാഹരണത്തിന്, കാണിച്ചിരിക്കുന്ന ഓർഗനൈസേഷന്റേതായിരിക്കില്ല ലോഗിൻ പേജ്."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"എന്തായാലും ബ്രൗസർ വഴി തുടരുക"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"ഈ സർട്ടിഫിക്കറ്റ്, വിശ്വസനീയ അതോറിറ്റിയിൽ നിന്നുള്ളതല്ല."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"സൈറ്റിന്റെ പേര്, സർട്ടിഫിക്കറ്റിലുള്ള പേരുമായി പൊരുത്തപ്പെടുന്നില്ല."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"ഈ സർട്ടിഫിക്കറ്റ് കാലഹരണപ്പെട്ടു."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"ഈ സർട്ടിഫിക്കറ്റിന് ഇപ്പോഴും സാധുതയില്ല."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"ഈ സർട്ടിഫിക്കറ്റിൽ അസാധുവായ തീയതിയാണുള്ളത്."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"ഈ സർട്ടിഫിക്കറ്റ് അസാധുവാണ്."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"അജ്ഞാത സർട്ടിഫിക്കറ്റ് പിശക്."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"സുരക്ഷാ മുന്നറിയിപ്പ്"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"സർട്ടിഫിക്കറ്റ് കാണുക"</string>
+    <string name="ok" msgid="2817931639040794018">"ശരി"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"വിലാസം:"</string>
+    <string name="page_info" msgid="4416941086705172545">"പേജ് വിവരം"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-mn/strings.xml b/packages/CaptivePortalLogin/res/values-mn/strings.xml
index 67670915..f11f1d6 100644
--- a/packages/CaptivePortalLogin/res/values-mn/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-mn/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Таны нэгдэх гэж буй сүлжээ аюулгүй байдлын асуудалтай байна."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Жишээлбэл нэвтрэх хуудас нь харагдах байгууллагынх биш байж болзошгүй."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Ямартаа ч хөтчөөр үргэлжлүүлэх"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Энэ сертификатыг итгэмжлэгдсэн байгууллагаас олгоогүй байна."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Сайтын нэр сертификат дээрх нэртэй таарахгүй байна."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Энэ сертификатын хугацаа дууссан байна."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Энэ сертификат одоогоор хүчингүй байна."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Энэ сертификатын огноо хүчингүй байна."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Энэ сертификат хүчингүй байна."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Сертификатын үл мэдэгдэх алдаа гарлаа."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Аюулгүй байдлын анхааруулга"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Сертификатыг харах"</string>
+    <string name="ok" msgid="2817931639040794018">"ЗА"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Хаяг:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Хуудасны мэдээлэл"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-mr/strings.xml b/packages/CaptivePortalLogin/res/values-mr/strings.xml
index 6ea9006..0adc92e 100644
--- a/packages/CaptivePortalLogin/res/values-mr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-mr/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"ज्या नेटवर्कमध्‍ये तुम्ही सामील होण्याचा प्रयत्न करीत आहात त्यात सुरक्षितता समस्या आहेत."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"उदाहरणार्थ, लॉगिन पृष्‍ठ कदाचित दर्शविलेल्या संस्थेच्या मालकीचे नसावे."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ब्राउझरद्वारे तरीही सुरु ठेवा"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"हे प्रमाणपत्र विश्वसनीय संस्थेने दिलेले नाही"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"साइटचे नाव प्रमाणपत्रावरील नावाशी जुळत नाही."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"हे प्रमाणपत्र एक्स्पायर झाले आहे."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"हे प्रमाणपत्र अजून योग्य नाही."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"या प्रमाणपत्राची तारीख चुकीची आहे."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"हे प्रमाणपत्र चुकीचे आहे."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"अज्ञात प्रमाणपत्र एरर."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"सुरक्षितता चेतावणी"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"प्रमाणपत्र पाहा"</string>
+    <string name="ok" msgid="2817931639040794018">"ठीक आहे"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"पत्ता:"</string>
+    <string name="page_info" msgid="4416941086705172545">"पेज माहिती"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ms/strings.xml b/packages/CaptivePortalLogin/res/values-ms/strings.xml
index aaa51c8..cc4957e 100644
--- a/packages/CaptivePortalLogin/res/values-ms/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ms/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Rangkaian yang anda cuba sertai mempunyai isu keselamatan."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Contohnya, halaman log masuk mungkin bukan milik organisasi yang ditunjukkan."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Teruskan juga melalui penyemak imbas"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Maklumat halaman"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Alamat:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Amaran keselamatan"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Lihat sijil"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sijil ini bukan daripada pihak berkuasa yang dipercayai."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Nama tapak tidak sepadan dengan nama pada sijil."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Sijil ini telah tamat tempoh."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sijil ini belum lagi sah."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Sijil ini mempunyai tarikh yang tidak sah."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Sijil ini tidak sah."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Ralat sijil tidak diketahui."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Sijil ini bukan daripada pihak berkuasa yang dipercayai."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Nama tapak tidak sepadan dengan nama pada sijil."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Sijil ini telah tamat tempoh."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Sijil ini belum sah."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Sijil ini mempunyai tarikh yang tidak sah."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Sijil ini tidak sah."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Ralat sijil tidak diketahui."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Amaran keselamatan"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Lihat sijil"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Alamat:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Maklumat halaman"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-my/strings.xml b/packages/CaptivePortalLogin/res/values-my/strings.xml
index 902834b..04a07a4 100644
--- a/packages/CaptivePortalLogin/res/values-my/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-my/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"သင်ချိတ်ဆက်ရန် ကြိုးစားနေသည့် ကွန်ရက်သည် လုံခြုံရေးပြဿနာ ရှိနေသည်။"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"ဥပမာ၊ ဝင်ရောက်ရန် စာမျက်နှာသည် ပြသထားသည့် အဖွဲ့အစည်းနှင့် သက်ဆိုင်မှု မရှိနိုင်ပါ။"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ဘရောက်ဇာမှတစ်ဆင့် ဆက်လုပ်ရန်"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"ဤအသိအမှတ်ပြုလက်မှတ်သည် ယုံကြည်ရသော စစ်ဆေးရေးအဖွဲ့ထံမှ မဟုတ်ပါ။"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"ဝဘ်ဆိုက်အမည်သည် အသိအမှတ်ပြုလက်မှတ်ရှိ အမည်နှင့် မကိုက်ညီပါ။"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"ဤအသိအမှတ်ပြုလက်မှတ် သက်တမ်းကုန်နေပါပြီ။"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"ဤအသိအမှတ်ပြုလက်မှတ်သည် မမှန်ကန်သေးပါ။"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"ဤအသိအမှတ်ပြုလက်မှတ်ရှိ ရက်စွဲ မမှန်ကန်ပါ။"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"ဤအသိအမှတ်ပြုလက်မှတ် မမှန်ကန်ပါ။"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"အသိအမှတ်ပြုလက်မှတ်ဆိုင်ရာ အမျိုးအမည်မသိ အမှား။"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"လုံခြုံရေး သတိပေးချက်"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"အသိအမှတ်ပြုလက်မှတ်ကို ကြည့်ရန်"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"လိပ်စာ-"</string>
+    <string name="page_info" msgid="4416941086705172545">"စာမျက်နှာ အချက်အလက်"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-nb/strings.xml b/packages/CaptivePortalLogin/res/values-nb/strings.xml
index 29c23ed..29ab438 100644
--- a/packages/CaptivePortalLogin/res/values-nb/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-nb/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Nettverket du prøver å logge på, har sikkerhetsproblemer."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Det er for eksempel mulig at påloggingssiden kanskje ikke tilhører organisasjonen som vises."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Fortsett likevel via nettleseren"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Sideinfo"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sikkerhetsadvarsel"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vis sertifikat"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sertifikatet er ikke fra en pålitelig myndighet."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Navnet på nettstedet samsvarer ikke med navnet på sertifikatet."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Sertifikatet er utløpt."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sertifikatet er ikke gyldig ennå."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dette sertifikatet har en ugyldig dato."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Dette sertifikatet er ugyldig."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Ukjent sertifikatfeil."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Sertifikatet er ikke fra en pålitelig myndighet."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Navnet på nettstedet samsvarer ikke med navnet på sertifikatet."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Sertifikatet er utløpt."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Sertifikatet er ikke gyldig ennå."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Dette sertifikatet har en ugyldig dato."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Dette sertifikatet er ugyldig."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Ukjent sertifikatfeil."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Sikkerhetsadvarsel"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Vis sertifikatet"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adresse:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Sideinformasjon"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ne/strings.xml b/packages/CaptivePortalLogin/res/values-ne/strings.xml
index 87a30c0..07d7231 100644
--- a/packages/CaptivePortalLogin/res/values-ne/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ne/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"तपाईँले सामेल हुन प्रयास गरिरहनु भएको नेटवर्कमा सुरक्षा मुद्दाहरू छन्।"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"उदाहरणका लागि, लग इन पृष्ठ देखाइएको संस्थाको नहुन सक्छ।"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"जे भए पनि ब्राउजर मार्फत जारी राख्नुहोस्"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"यो विश्वसनीय प्राधिकरणबाट उपलब्ध गराइएको प्रमाणपत्र होइन।"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"प्रमाणपत्रमा भएको नाम साइटमा भएको नामसँग मेल खाँदैन।"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"यो प्रमाणपत्रको म्याद समाप्त भयो।"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"यो प्रमाणपत्र अझै मान्य छैन।"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"यो प्रमाणपत्रमा कुनै अमान्य मिति छ।"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"यो प्रमाणपत्र अमान्य छ।"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"प्रमाणपत्रसम्बन्धी अज्ञात त्रुटि।"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"सुरक्षासम्बन्धी चेतावनी"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"प्रमाणपत्र हेर्नुहोस्‌"</string>
+    <string name="ok" msgid="2817931639040794018">"ठिक छ"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"ठेगाना:"</string>
+    <string name="page_info" msgid="4416941086705172545">"पृष्ठको जानकारी"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-nl/strings.xml b/packages/CaptivePortalLogin/res/values-nl/strings.xml
index 2cbca06..a4df7b7 100644
--- a/packages/CaptivePortalLogin/res/values-nl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-nl/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Het netwerk waarmee u verbinding probeert te maken, heeft beveiligingsproblemen."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Zo hoort de weergegeven inlogpagina misschien niet bij de weergegeven organisatie."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Toch doorgaan via browser"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Pagina-informatie"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Beveiligingsmelding"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Certificaat weergeven"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Dit is geen certificaat van een vertrouwde autoriteit."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"De naam van deze site komt niet overeen met de naam op het certificaat."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Dit certificaat is verlopen."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Dit certificaat is nog niet geldig."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dit certificaat heeft een ongeldige datum."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Dit certificaat is ongeldig."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Onbekende certificaatfout."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Dit is geen certificaat van een vertrouwde autoriteit."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"De naam van deze site komt niet overeen met de naam op het certificaat."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Dit certificaat is verlopen."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Dit certificaat is nog niet geldig."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Dit certificaat heeft een ongeldige datum."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Dit certificaat is ongeldig."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Onbekende certificaatfout."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Beveiligingswaarschuwing"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Certificaat weergeven"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adres:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Paginagegevens"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-or/strings.xml b/packages/CaptivePortalLogin/res/values-or/strings.xml
index 80074c3..f4c5dac 100644
--- a/packages/CaptivePortalLogin/res/values-or/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-or/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"ଆପଣ ଯୋଗ ଦେବାକୁ ଚେଷ୍ଟା କରୁଥିବା ନେଟ୍‌ୱର୍କର ସୁରକ୍ଷା ସମସ୍ୟା ଅଛି।"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"ଉଦାହରଣସ୍ୱରୂପ, ଲଗଇନ୍‍ ପୃଷ୍ଠା ଦେଖାଯାଇଥିବା ସଂସ୍ଥାର ନହୋଇଥାଇପାରେ।"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ବ୍ରାଉଜର୍‍ ଜରିଆରେ ଯେମିତିବି ହେଉ ଜାରି ରଖନ୍ତୁ"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"ଏହି ସାର୍ଟିଫିକେଟ୍‍ ଏକ ବିଶ୍ବସ୍ତ କର୍ତ୍ତୃପକ୍ଷଙ୍କ ଠାରୁ ନୁହେଁ।"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"ସାଇଟ୍‍ର ନାମ ସାର୍ଟିଫିକେଟ୍‍‍‍‍ର ନାମ ସହ ମିଶୁ ନାହିଁ।"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"ଏହି ସାର୍ଟିଫିକେଟ୍‍ ସମୟସୀମା ଶେଷ ହୋଇଛି।"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"ଏହି ସାର୍ଟିଫିକେଟ୍‍ ବର୍ତ୍ତମାନ ପର୍ଯ୍ୟନ୍ତ ବୈଧ ନୁହେଁ।"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"ଏହି ସାର୍ଟିଫିକେଟ୍‍‍‍‍‍ରେ ଏକ ଅବୈଧ ତାରିଖ ରହିଛି।"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"ଏହି ସାର୍ଟିଫିକେଟ୍‍ ବୈଧ ନୁହେଁ।"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"ଅଜଣା ସାର୍ଟିଫିକେଟ୍‍ ତ୍ରୁଟି।"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"ସୁରକ୍ଷା ଚେତାବନୀ"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"ସାର୍ଟିଫିକେଟ୍‍ ଦେଖନ୍ତୁ"</string>
+    <string name="ok" msgid="2817931639040794018">"ଠିକ୍‍ ଅଛି"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"ଠିକଣା:"</string>
+    <string name="page_info" msgid="4416941086705172545">"ପୃଷ୍ଠା ସୂଚନା"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-pa/strings.xml b/packages/CaptivePortalLogin/res/values-pa/strings.xml
index 03e252f..b0d6187 100644
--- a/packages/CaptivePortalLogin/res/values-pa/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pa/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"ਤੁਹਾਡੇ ਦੁਆਰਾ ਸ਼ਾਮਿਲ ਹੋਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੇ ਜਾ ਰਹੇ ਨੈੱਟਵਰਕ ਵਿੱਚ ਸੁਰੱਖਿਆ ਸੰਬੰਧੀ ਸਮੱਸਿਆਵਾਂ ਹਨ।"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"ਉਦਾਹਰਣ ਵੱਜੋਂ, ਲੌਗ-ਇਨ ਪੰਨਾ ਦਿਖਾਈ ਗਈ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਨਹੀਂ ਹੋ ਸਕਦਾ ਹੈ।"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ਬ੍ਰਾਊਜ਼ਰ ਰਾਹੀਂ ਫਿਰ ਵੀ ਜਾਰੀ ਰੱਖੋ"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"ਇਹ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਕਿਸੇ ਭਰੋਸੇਯੋਗ ਅਥਾਰਿਟੀ ਦਾ ਨਹੀਂ ਹੈ।"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"ਸਾਈਟ ਦਾ ਨਾਮ ਪ੍ਰਮਾਣ-ਪੱਤਰ \'ਤੇ ਦਿੱਤੇ ਨਾਮ ਨਾਲ ਮੇਲ ਨਹੀਂ ਖਾਂਦਾ ਹੈ।"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"ਇਸ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਦੀ ਮਿਆਦ ਸਮਾਪਤ ਹੋ ਗਈ ਹੈ।"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"ਇਹ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਹਾਲੇ ਵੈਧ ਨਹੀਂ ਹੈ।"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"ਇਸ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਦੀ ਤਾਰੀਖ ਅਵੈਧ ਹੈ।"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"ਇਹ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਵੈਧ ਹੈ।"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"ਅਗਿਆਤ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਗੜਬੜ।"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"ਸੁਰੱਖਿਆ ਚਿਤਾਵਨੀ"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"ਪ੍ਰਮਾਣ-ਪੱਤਰ ਦੇਖੋ"</string>
+    <string name="ok" msgid="2817931639040794018">"ਠੀਕ ਹੈ"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"ਪਤਾ:"</string>
+    <string name="page_info" msgid="4416941086705172545">"ਪੰਨੇ ਦੀ ਜਾਣਕਾਰੀ"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-pl/strings.xml b/packages/CaptivePortalLogin/res/values-pl/strings.xml
index 9ba066e..178734d 100644
--- a/packages/CaptivePortalLogin/res/values-pl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pl/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"W sieci, z którą próbujesz się połączyć, występują problemy z zabezpieczeniami."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Na przykład strona logowania może nie należeć do wyświetlanej organizacji."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Kontynuuj mimo to w przeglądarce"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Informacje o stronie"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Ostrzeżenie zabezpieczeń"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Wyświetl certyfikat"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Certyfikat nie pochodzi od zaufanego urzędu."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Nazwa witryny nie pasuje do nazwy na certyfikacie."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Ten certyfikat wygasł."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Certyfikat nie jest jeszcze ważny."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Certyfikat ma nieprawidłową datę."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Certyfikat jest nieprawidłowy."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Nieznany błąd certyfikatu"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Certyfikat nie pochodzi od zaufanego urzędu."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Nazwa witryny nie pasuje do nazwy na certyfikacie."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Certyfikat wygasł."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Certyfikat nie jest jeszcze ważny."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Certyfikat ma nieprawidłową datę."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Certyfikat jest nieprawidłowy."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Nieznany błąd certyfikatu."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Ostrzeżenie dotyczące bezpieczeństwa"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Wyświetl certyfikat"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adres:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informacje o stronie"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-pt-rBR/strings.xml b/packages/CaptivePortalLogin/res/values-pt-rBR/strings.xml
index 3d1064c..3aa82c4 100644
--- a/packages/CaptivePortalLogin/res/values-pt-rBR/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pt-rBR/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"A rede à qual você está tentando se conectar tem problemas de segurança."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuar mesmo assim pelo navegador"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Esse certificado não é de uma autoridade confiável."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"O nome do site não corresponde ao nome no certificado."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Esse certificado expirou."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Esse certificado ainda não é válido."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"A data desse certificado é inválida."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Esse certificado é inválido."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Erro de certificado desconhecido."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Aviso de segurança"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Ver certificado"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Endereço:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informações da página"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml b/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml
index 5bef235..72d62a3 100644
--- a/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"A rede à qual está a tentar aceder tem problemas de segurança."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Por exemplo, a página de início de sessão pode não pertencer à entidade apresentada."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuar mesmo assim através do navegador"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Informações da página"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Endereço:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Aviso de segurança"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Ver certificado"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado não pertence a uma autoridade fidedigna."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"O nome do Web site não corresponde ao nome constante no certificado."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado expirou."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado ainda não é válido."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Este certificado tem uma data inválida."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado é inválido."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Erro: certificado desconhecido."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Este certificado não pertence a uma autoridade fidedigna."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"O nome do site não corresponde ao nome constante no certificado."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Este certificado expirou."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Este certificado ainda não é válido."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Este certificado tem uma data inválida."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Este certificado é inválido."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Erro de certificado desconhecido."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Aviso de segurança"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Ver certificado"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Endereço:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informações da página"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-pt/strings.xml b/packages/CaptivePortalLogin/res/values-pt/strings.xml
index ebe4148..3aa82c4 100644
--- a/packages/CaptivePortalLogin/res/values-pt/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pt/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"A rede à qual você está tentando se conectar tem problemas de segurança."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuar mesmo assim pelo navegador"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Informações da página"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Endereço:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Aviso de segurança"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visualizar certificado"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado não é de uma autoridade confiável."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"O nome do site não corresponde ao nome no certificado."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado expirou."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado ainda não é válido."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Este certificado tem uma data inválida."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado é inválido."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Erro de certificado desconhecido."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Esse certificado não é de uma autoridade confiável."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"O nome do site não corresponde ao nome no certificado."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Esse certificado expirou."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Esse certificado ainda não é válido."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"A data desse certificado é inválida."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Esse certificado é inválido."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Erro de certificado desconhecido."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Aviso de segurança"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Ver certificado"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Endereço:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informações da página"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ro/strings.xml b/packages/CaptivePortalLogin/res/values-ro/strings.xml
index e2e4eac..e3fc191 100644
--- a/packages/CaptivePortalLogin/res/values-ro/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ro/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Rețeaua la care încercați să vă conectați are probleme de securitate."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"De exemplu, este posibil ca pagina de conectare să nu aparțină organizației afișate."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuați oricum prin browser"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Informaţii pagină"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adresă:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Avertisment de securitate"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vizualizaţi certificatul"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Acest certificat nu provine de la o autoritate de încredere."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Numele acestui site nu se potriveşte cu numele de pe certificat."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Acest certificat a expirat."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Acest certificat nu este încă valid."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Acest certificat are o dată nevalidă."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Acest certificat este nevalid."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Eroare de certificat necunoscută."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Acest certificat nu provine de la o autoritate de încredere."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Numele acestui site nu se potrivește cu numele de pe certificat."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Acest certificat a expirat."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Acest certificat nu este încă valid."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Acest certificat are o dată nevalidă."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Acest certificat este nevalid."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Eroare de certificat necunoscută."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Avertisment de securitate"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Vizualizați certificatul"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adresă:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informații despre pagină"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ru/strings.xml b/packages/CaptivePortalLogin/res/values-ru/strings.xml
index c0153e6..a976f57 100644
--- a/packages/CaptivePortalLogin/res/values-ru/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ru/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Сеть, к которой вы хотите подключиться, небезопасна."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Например, страница входа в аккаунт может быть фиктивной."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Игнорировать и открыть браузер"</string>
-    <string name="ok" msgid="1509280796718850364">"ОК"</string>
-    <string name="page_info" msgid="4048529256302257195">"Информация о странице"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Адрес:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Угроза безопасности"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Просмотреть сертификат"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Этот сертификат получен из ненадежных источников."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Название сайта не соответствует названию в сертификате."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Срок действия сертификата истек."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Сертификат еще не действителен."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Дата этого сертификата недействительна."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Этот сертификат недействителен."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Неизвестная ошибка сертификата."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Этот сертификат получен из ненадежных источников."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Название сайта отличается от указанного в сертификате."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Срок действия сертификата истек."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Сертификат ещё не действителен."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Дата сертификата недействительна."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Сертификат недействителен."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Неизвестная ошибка, связанная с сертификатом."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Предупреждение об опасности"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Показать сертификат"</string>
+    <string name="ok" msgid="2817931639040794018">"ОК"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Адрес:"</string>
+    <string name="page_info" msgid="4416941086705172545">"О странице"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-si/strings.xml b/packages/CaptivePortalLogin/res/values-si/strings.xml
index a307913..edfe716 100644
--- a/packages/CaptivePortalLogin/res/values-si/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-si/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"ඔබ සම්බන්ධ වීමට උත්සහ කරන ජාලයේ ආරක්ෂක ගැටළු ඇත."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"උදාහරණයක් ලෙස, පුරනය වන පිටුව පෙන්වා ඇති සංවිධානයට අයිති නැති විය හැක."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"කෙසේ වුවත් බ්‍රවුසරය හරහා ඉදිරියට යන්න"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"මෙම සහතිකය විශ්වාසී අධිකාරියකින් නොවේ."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"අඩවියේ නම සහතිකයේ නමට නොගැළපේ."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"මෙම සහතිකය කල් ඉකුත් වී ඇත."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"මෙම සහතිකය තවම වලංගු නැත."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"මෙම සහතිකයට වලංගු නොවන දිනයක් ඇත."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"මෙම සහතිකය වලංගු නොවේ."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"නොදන්නා සහතික දෝෂයකි."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"ආරක්ෂක අවවාදයයි"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"සහතිකය බලන්න"</string>
+    <string name="ok" msgid="2817931639040794018">"හරි"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"ලිපිනය:"</string>
+    <string name="page_info" msgid="4416941086705172545">"පිටු තොරතුරු"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-sk/strings.xml b/packages/CaptivePortalLogin/res/values-sk/strings.xml
index 8ba24b1..c1100b8 100644
--- a/packages/CaptivePortalLogin/res/values-sk/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sk/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Sieť, ku ktorej sa pokúšate pripojiť, má problémy so zabezpečením"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Napríklad prihlasovacia stránka nemusí patriť uvedenej organizácii."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Pokračovať pomocou prehliadača"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Informácie o stránke"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adresa:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Upozornenie zabezpečenia"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Zobraziť certifikát"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Tento certifikát nepochádza od dôveryhodnej autority."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Názov stránky sa nezhoduje s názvom uvedeným v certifikáte."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Platnosť certifikátu skončila."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Tento certifikát zatiaľ nie je platný."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Tento certifikát má neplatný dátum."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Tento certifikát je neplatný."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Neznáma chyba certifikátu."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Tento certifikát nepochádza od dôveryhodnej autority."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Názov stránky sa nezhoduje s názvom uvedeným v certifikáte."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Platnosť certifikátu skončila."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Tento certifikát zatiaľ nie je platný."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Tento certifikát má neplatný dátum."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Tento certifikát je neplatný."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Neznáma chyba certifikátu."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Bezpečnostné upozornenie"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Zobraziť certifikát"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adresa:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informácie o stránke"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-sl/strings.xml b/packages/CaptivePortalLogin/res/values-sl/strings.xml
index b7d9a8a..b254240 100644
--- a/packages/CaptivePortalLogin/res/values-sl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sl/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Omrežje, ki se mu poskušate pridružiti, ima varnostne težave."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Stran za prijavo na primer morda ne pripada prikazani organizaciji."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Vseeno nadaljuj v brskalniku"</string>
-    <string name="ok" msgid="1509280796718850364">"V redu"</string>
-    <string name="page_info" msgid="4048529256302257195">"Podatki o strani"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Naslov:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Varnostno opozorilo"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Prikaži potrdilo"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Potrdila ni izdal zaupanja vreden overitelj."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Ime spletnega mesta se ne ujema z imenom na potrdilu."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Potrdilo je poteklo."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"To potrdilo še ni veljavno."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Potrdilo ima neveljaven datum."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"To potrdilo ni veljavno."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Neznana napaka potrdila."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Potrdila ni izdal zaupanja vreden overitelj."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Ime spletnega mesta se ne ujema z imenom na potrdilu."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Potrdilo je poteklo."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"To potrdilo še ni veljavno."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"To potrdilo ima neveljaven datum."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"To potrdilo ni veljavno."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Neznana napaka potrdila."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Varnostno opozorilo"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Prikaži potrdilo"</string>
+    <string name="ok" msgid="2817931639040794018">"V redu"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Naslov:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Podatki o strani"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-sq/strings.xml b/packages/CaptivePortalLogin/res/values-sq/strings.xml
index b06da6d..a178c40 100644
--- a/packages/CaptivePortalLogin/res/values-sq/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sq/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Rrjeti në të cilin po përpiqesh të bashkohesh ka probleme sigurie."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"për shembull, faqja e identifikimit mund të mos i përkasë organizatës së shfaqur."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Vazhdo gjithsesi nëpërmjet shfletuesit"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Kjo certifikatë nuk është nga një autoritet i besuar."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Emri i sajtit nuk përputhet me emrin në certifikatë."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Kjo certifikatë ka skaduar."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Kjo certifikatë nuk është ende e vlefshme."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Kjo certifikatë ka një datë të pavlefshme."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Kjo certifikatë është e pavlefshme."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Gabim i panjohur i certifikatës."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Paralajmërim për sigurinë"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Shiko certifikatën"</string>
+    <string name="ok" msgid="2817931639040794018">"Në rregull"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adresa:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Informacionet e faqes"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-sr/strings.xml b/packages/CaptivePortalLogin/res/values-sr/strings.xml
index 967c8ba..6b08369 100644
--- a/packages/CaptivePortalLogin/res/values-sr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sr/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Мрежа којој покушавате да се придружите има безбедносних проблема."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"На пример, страница за пријављивање можда не припада приказаној организацији."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Ипак настави преко прегледача"</string>
-    <string name="ok" msgid="1509280796718850364">"Потврди"</string>
-    <string name="page_info" msgid="4048529256302257195">"Информације о страници"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Адреса:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Безбедносно упозорење"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Прикажи сертификат"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Овај сертификат не потиче од поузданог ауторитета."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Назив сајта се не подудара са називом на сертификату."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Овај сертификат је истекао."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Овај сертификат још увек није важећи."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Датум овог сертификата је неважећи."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Овај сертификат је неважећи."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Непозната грешка сертификата."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Овај сертификат не потиче из поузданог извора."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Назив сајта се не подудара са називом на сертификату."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Овај сертификат је истекао."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Овај сертификат још увек није важећи."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Датум овог сертификата је неважећи."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Овај сертификат је неважећи."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Непозната грешка сертификата."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Безбедносно упозорење"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Прикажи сертификат"</string>
+    <string name="ok" msgid="2817931639040794018">"Потврди"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Адреса:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Информације о страници"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-sv/strings.xml b/packages/CaptivePortalLogin/res/values-sv/strings.xml
index 75356f0..7fe5432 100644
--- a/packages/CaptivePortalLogin/res/values-sv/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sv/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Nätverket du försöker ansluta till har säkerhetsproblem."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Det kan t.ex. hända att inloggningssidan inte tillhör den organisation som visas."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Fortsätt ändå via webbläsaren"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Sidinformation"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adress:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Säkerhetsvarning"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visa certifikat"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Certifikatet kommer inte från en betrodd utfärdare."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Webbplatsens namn stämmer inte med namnet på certifikatet."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Certifikatet har upphört att gälla."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Certifikatet är inte giltigt än."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Det här certifikatet har ett ogiltigt datum."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Certifikatet är ogiltigt."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Okänt certifikatfel."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Certifikatet kommer inte från en betrodd utfärdare."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Webbplatsens namn matchar inte namnet på certifikatet."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Det här certifikatet har löpt ut."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Det här certifikatet är inte giltigt än."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Datumet för det här certifikatet är ogiltigt."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Det här certifikatet är ogiltigt."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Okänt certifikatfel."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Säkerhetsvarning"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Visa certifikat"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adress:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Sidinformation"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-sw/strings.xml b/packages/CaptivePortalLogin/res/values-sw/strings.xml
index feb2dde..297b72d 100644
--- a/packages/CaptivePortalLogin/res/values-sw/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sw/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Mtandao unaojaribu kujiunga nao una matatizo ya usalama."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Kwa mfano, ukurasa wa kuingia katika akaunti unaweza usiwe unamilikiwa na shirika lililoonyeshwa."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Endelea hata hivyo kupitia kivinjari"</string>
-    <string name="ok" msgid="1509280796718850364">"Sawa"</string>
-    <string name="page_info" msgid="4048529256302257195">"Maelezo ya ukurasa"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Anwani:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Ilani ya usalama"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Tazama cheti"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Cheti hiki hakijatoka kwa mamlaka inayoaminika."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Jina la tovuti halilingani na jina lililo katika cheti."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Cheti hiki kimepitwa na muda"</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Cheti bado si halali."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Cheti hiki kina tarehe batili."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Hati hii ni batili."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Hitilafu isiyojulikana ya cheti."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Cheti hiki hakijatoka kwa mamlaka inayoaminika."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Jina la tovuti halilingani na jina lililo katika cheti."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Muda wa kutumia cheti hiki umeisha."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Cheti hiki bado si halali."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Tarehe ya cheti hiki si sahihi."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Cheti hiki si sahihi."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Hitilafu isiyojulikana ya cheti."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Ilani ya usalama"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Angalia cheti"</string>
+    <string name="ok" msgid="2817931639040794018">"Sawa"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Anwani:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Maelezo ya ukurasa"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ta/strings.xml b/packages/CaptivePortalLogin/res/values-ta/strings.xml
index 6a60ed7..4517d15 100644
--- a/packages/CaptivePortalLogin/res/values-ta/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ta/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"நீங்கள் சேர முயற்சிக்கும் நெட்வொர்க்கில் பாதுகாப்புச் சிக்கல்கள் உள்ளன."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"எடுத்துக்காட்டாக, உள்நுழைவுப் பக்கமானது காட்டப்படும் அமைப்பிற்குச் சொந்தமானதாக இல்லாமல் இருக்கலாம்."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"பரவாயில்லை, உலாவி வழியாகத் தொடரவும்"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"இந்தச் சான்றிதழ் நம்பகமான நிறுவனத்தால் அங்கீகரிக்கப்படவில்லை."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"சான்றிதழிலுள்ள பெயருடன் வலைதளத்தின் பெயர் பொருந்தவில்லை."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"இந்தச் சான்றிதழ் காலாவதியாகிவிட்டது."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"இந்தச் சான்றிதழ் இன்னும் செல்லாததாக உள்ளது."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"இந்தச் சான்றிதழில் தவறான தேதி உள்ளது."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"இந்தச் சான்றிதழ் செல்லாதது."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"சான்றிதழில் அறியப்படாத பிழை உள்ளது."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"பாதுகாப்பு எச்சரிக்கை"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"சான்றிதழைக் காட்டு"</string>
+    <string name="ok" msgid="2817931639040794018">"சரி"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"முகவரி:"</string>
+    <string name="page_info" msgid="4416941086705172545">"பக்கத் தகவல்"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-te/strings.xml b/packages/CaptivePortalLogin/res/values-te/strings.xml
index c209d34..9bb4c11 100644
--- a/packages/CaptivePortalLogin/res/values-te/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-te/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"మీరు చేరడానికి ప్రయత్నిస్తున్న నెట్‌వర్క్ భద్రతా సమస్యలను కలిగి ఉంది."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"ఉదాహరణకు, లాగిన్ పేజీ చూపిన సంస్థకు చెందినది కాకపోవచ్చు."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ఏదేమైనా బ్రౌజర్ ద్వారా కొనసాగించు"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"ఈ సర్టిఫికెట్ విశ్వసనీయ అధికార సంస్థ నుండి కాదు."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"సైట్ యొక్క పేరు సర్టిఫికెట్‌లోని పేరుతో సరిపోలలేదు."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"ఈ సర్టిఫికెట్ గడువు ముగిసింది."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"ఈ సర్టిఫికెట్ ఇప్పటికీ చెల్లదు."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"ఈ సర్టిఫికెట్ చెల్లని తేదీని కలిగి ఉంది."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"ఈ సర్టిఫికెట్ చెల్లుబాటు కాదు."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"తెలియని సర్టిఫికెట్ ఎర్రర్."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"భద్రతా హెచ్చరిక"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"సర్టిఫికెట్‌ని చూడండి"</string>
+    <string name="ok" msgid="2817931639040794018">"సరే"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"చిరునామా:"</string>
+    <string name="page_info" msgid="4416941086705172545">"పేజీ సమాచారం"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-th/strings.xml b/packages/CaptivePortalLogin/res/values-th/strings.xml
index 11a2131..739b505 100644
--- a/packages/CaptivePortalLogin/res/values-th/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-th/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"เครือข่ายที่คุณพยายามเข้าร่วมมีปัญหาด้านความปลอดภัย"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"ตัวอย่างเช่น หน้าเข้าสู่ระบบอาจไม่ใช่ขององค์กรที่แสดงไว้"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ดำเนินการต่อผ่านเบราว์เซอร์"</string>
-    <string name="ok" msgid="1509280796718850364">"ตกลง"</string>
-    <string name="page_info" msgid="4048529256302257195">"ข้อมูลหน้าเว็บ"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"ที่อยู่:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"คำเตือนเกี่ยวกับความปลอดภัย"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"ดูใบรับรอง"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"ใบรับรองนี้ไม่ได้มาจากผู้ออกที่เชื่อถือได้"</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"ชื่อไซต์ไม่ตรงกับในใบรับรอง"</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"ใบรับรองนี้หมดอายุแล้ว"</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"ใบรับรองนี้ยังใช้งานไม่ได้"</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"ใบรับรองนี้มีวันที่ไม่ถูกต้อง"</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"ใบรับรองนี้ไม่ถูกต้อง"</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"ข้อผิดพลาดใบรับรองที่ไม่รู้จัก"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"ใบรับรองนี้ไม่ได้มาจากผู้ออกที่เชื่อถือได้"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"ชื่อเว็บไซต์ไม่ตรงกับในใบรับรอง"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"ใบรับรองนี้หมดอายุแล้ว"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"ใบรับรองนี้ยังใช้งานไม่ได้"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"วันที่ในใบรับรองนี้ไม่ถูกต้อง"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"ใบรับรองนี้ไม่ถูกต้อง"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"ข้อผิดพลาดใบรับรองที่ไม่รู้จัก"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"การแจ้งเตือนเกี่ยวกับความปลอดภัย"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"ดูใบรับรอง"</string>
+    <string name="ok" msgid="2817931639040794018">"ตกลง"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"ที่อยู่:"</string>
+    <string name="page_info" msgid="4416941086705172545">"ข้อมูลหน้าเว็บ"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-tl/strings.xml b/packages/CaptivePortalLogin/res/values-tl/strings.xml
index 07a2479..483a589 100644
--- a/packages/CaptivePortalLogin/res/values-tl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-tl/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"May mga isyu sa seguridad ang network kung saan mo sinusubukang sumali."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Halimbawa, maaaring hindi sa organisasyong ipinapakita ang page sa pag-log in."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Magpatuloy pa rin sa pamamagitan ng browser"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Impormasyon ng pahina"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Address:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Babala sa seguridad"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Tingnan ang certificate"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ang certificate ay hindi mula sa isang pinagkakatiwalaang kinauukulan."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Ang pangalan ng site ay hindi tumutugma sa pangalan sa certificate."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Nag-expire na ang certificate na ito."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Wala pang bisa ang certificate na ito."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Ang certificate ay mayroong di-wastong petsa."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Di-wasto ang certificate na ito."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Hindi kilalang error ng certificate."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Ang certificate na ito ay mula sa hindi pinagkakatiwalaang awtoridad."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Ang pangalan ng site ay hindi tumutugma sa pangalan sa certificate."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Nag-expire na ang certificate na ito."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Hindi pa valid ang certificate na ito."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"May invalid na petsa ang certificate na ito."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Invalid ang certificate na ito."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Hindi kilalang error sa certificate."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Babala sa seguridad"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Tingnan ang certificate"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Address:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Impormasyon ng page"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-tr/strings.xml b/packages/CaptivePortalLogin/res/values-tr/strings.xml
index cdedd33..f51cfbd 100644
--- a/packages/CaptivePortalLogin/res/values-tr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-tr/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Katılmaya çalıştığınız ağda güvenlik sorunları var."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Örneğin, giriş sayfası, gösterilen kuruluşa ait olmayabilir."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Yine de tarayıcıyla devam et"</string>
-    <string name="ok" msgid="1509280796718850364">"Tamam"</string>
-    <string name="page_info" msgid="4048529256302257195">"Sayfa bilgileri"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Güvenlik uyarısı"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Sertifikayı görüntüle"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Bu sertifika güvenilir bir yetkiliden değil."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Sitenin adı sertifika üzerindeki adla eşleşmiyor."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Bu sertifikanın süresi dolmuş."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Bu sertifika henüz geçerli değil."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Bu sertifikanın tarihi geçersiz."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Bu sertifika geçersiz."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Bilinmeyen sertifika hatası."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Bu sertifika güvenilir bir yetkiliden değil."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Sitenin adı sertifika üzerindeki adla eşleşmiyor."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Bu sertifikanın süresi dolmuş."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Bu sertifika henüz geçerli değil."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Bu sertifikanın tarihi geçersiz."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Bu sertifika geçersiz."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Bilinmeyen sertifika hatası."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Güvenlik uyarısı"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Sertifikayı göster"</string>
+    <string name="ok" msgid="2817931639040794018">"Tamam"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Adres:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Sayfa bilgileri"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-uk/strings.xml b/packages/CaptivePortalLogin/res/values-uk/strings.xml
index 0f4cd16..c1a5d05 100644
--- a/packages/CaptivePortalLogin/res/values-uk/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-uk/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"У мережі, до якої ви намагаєтеся під’єднатись, є проблеми з безпекою."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Наприклад, сторінка входу може не належати вказаній організації."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Усе одно продовжити у веб-переглядачі"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Інфо про стор."</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Адреса:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Застереж. про небезп."</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Переглянути сертиф."</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Сертифікат видано ненадійним центром сертифікації."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Назва сайту не збігається з назвою в сертифікаті."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Термін дії сертиф. завершився."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Цей сертифікат ще не дійсний."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Цей сертифікат має недійсну дату."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Цей сертифікат недійсний."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Помилка невідомого сертифіката."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Сертифікат видано ненадійним центром сертифікації."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Назва сайту не збігається з назвою в сертифікаті."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Термін дії сертифіката закінчився."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Цей сертифікат ще не дійсний."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Цей сертифікат має недійсну дату."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Цей сертифікат недійсний."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Помилка невідомого сертифіката."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Застереження про небезпеку"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Переглянути сертифікат"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Адреса:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Інформація про сторінку"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ur/strings.xml b/packages/CaptivePortalLogin/res/values-ur/strings.xml
index 05d8fb9..e6f8539 100644
--- a/packages/CaptivePortalLogin/res/values-ur/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ur/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"جس نیٹ ورک میں آپ شامل ہونے کی کوشش کر رہے ہیں اس میں سیکیورٹی کے مسائل ہیں۔"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"مثال کے طور پر ہو سکتا ہے کہ لاگ ان صفحہ دکھائی گئی تنظیم سے تعلق نہ رکھتا ہو۔"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"براؤزر کے ذریعے بہرحال جاری رکھیں"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"یہ سرٹیفکیٹ قابل اعتماد اتھارٹی سے حاصل شدہ نہیں ہے۔"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"سائٹ کا نام سرٹیفکیٹ پر موجود نام سے مماثل نہیں ہے۔"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"اس سرٹیفکیٹ کی میعاد ختم ہو گئی ہے۔"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"یہ سرٹیفکیٹ ابھی تک درست نہیں ہے۔"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"اس سرٹیفکیٹ میں ایک غلط تاریخ ہے۔"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"یہ سرٹیفیکیٹ غلط ہے۔"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"سرٹیفکیٹ کی نامعلوم خرابی۔"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"سیکیورٹی وارننگ"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"سرٹیفکیٹ دیکھیں"</string>
+    <string name="ok" msgid="2817931639040794018">"ٹھیک ہے"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"پتہ:"</string>
+    <string name="page_info" msgid="4416941086705172545">"صفحہ کی معلومات"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-uz/strings.xml b/packages/CaptivePortalLogin/res/values-uz/strings.xml
index cac96ea..4009db6a 100644
--- a/packages/CaptivePortalLogin/res/values-uz/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-uz/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Siz ulanmoqchi bo‘lgan tarmoqda xavfsizlik bilan bog‘liq muammolar mavjud."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Masalan, tizimga kirish sahifasi ko‘rsatilgan tashkilotga tegishli bo‘lmasligi mumkin."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"E’tiborsiz qoldirilsin va brauzer ochilsin"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Bu sertifikat ishonchsiz manbadan olingan."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Sayt nomi sertifikatdagi nomga mos emas."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Bu sertifikat muddati tugagan."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Bu sertifikat hali yaroqli emas."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Bu sertifikatdagi sana xato."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Bu sertifikat yaroqsiz."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Sertifikatga aloqador notanish xato."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Xavfsizlikka oid ogohlantirish"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Sertifikatni ochish"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Manzil:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Sahifa haqida"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-vi/strings.xml b/packages/CaptivePortalLogin/res/values-vi/strings.xml
index 9c702b9..bd4e96a 100644
--- a/packages/CaptivePortalLogin/res/values-vi/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-vi/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Mạng mà bạn đang cố gắng tham gia có vấn đề về bảo mật."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Ví dụ, trang đăng nhập có thể không thuộc về tổ chức được hiển thị."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Vẫn tiếp tục qua trình duyệt"</string>
-    <string name="ok" msgid="1509280796718850364">"OK"</string>
-    <string name="page_info" msgid="4048529256302257195">"Thông tin trang"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Địa chỉ:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Cảnh báo bảo mật"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Xem chứng chỉ"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Chứng chỉ này không xuất phát từ tổ chức phát hành đáng tin cậy."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Tên của trang web không khớp với tên trên chứng chỉ."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Chứng chỉ này đã hết hạn."</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Chứng chỉ này chưa hợp lệ."</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Chứng chỉ này có ngày không hợp lệ."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Chứng chỉ này không hợp lệ."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Lỗi chứng chỉ không xác định."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Chứng chỉ này không xuất phát từ tổ chức phát hành đáng tin cậy."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Tên của trang web không khớp với tên trên chứng chỉ."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Chứng chỉ này đã hết hạn."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Chứng chỉ này chưa hợp lệ."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Chứng chỉ này có ngày không hợp lệ."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Chứng chỉ này không hợp lệ."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Lỗi chứng chỉ không xác định."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Cảnh báo bảo mật"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Xem chứng chỉ"</string>
+    <string name="ok" msgid="2817931639040794018">"OK"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Địa chỉ:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Thông tin trang"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml b/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml
index 70c2a08..5beaa2e 100644
--- a/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"您尝试加入的网络存在安全问题。"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"例如,登录页面可能并不属于页面上显示的单位。"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"仍然通过浏览器继续操作"</string>
-    <string name="ok" msgid="1509280796718850364">"确定"</string>
-    <string name="page_info" msgid="4048529256302257195">"网页信息"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"网址:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"安全警告"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"查看证书"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"该证书并非来自可信的授权中心。"</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"网站的名称与证书上的名称不一致。"</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"该证书已过期。"</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"该证书尚未生效。"</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"该证书的日期无效。"</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"该证书无效。"</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"未知证书错误。"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"该证书并非来自可信的授权中心。"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"网站的名称与证书上的名称不一致。"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"该证书已过期。"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"该证书尚未生效。"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"该证书的日期无效。"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"该证书无效。"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"未知证书错误。"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"安全警告"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"查看证书"</string>
+    <string name="ok" msgid="2817931639040794018">"确定"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"地址:"</string>
+    <string name="page_info" msgid="4416941086705172545">"页面信息"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml b/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml
index df1c700..7987023 100644
--- a/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"您正在嘗試加入的網絡有安全性問題。"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"例如,登入頁面並不屬於所顯示的機構。"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"透過瀏覽器繼續"</string>
-    <string name="ok" msgid="1509280796718850364">"確定"</string>
-    <string name="page_info" msgid="4048529256302257195">"網頁資訊"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"地址:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"安全性警告"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"查看憑證"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"這個憑證並非由受信任的權威機構發出。"</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"網站名稱與憑證上的名稱不相符。"</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"這個憑證已過期。"</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"這個憑證尚未生效。"</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"此憑證的日期無效。"</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"此憑證是無效的。"</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"不明的憑證錯誤。"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"此憑證並非由信任的機構發出。"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"網站名稱與憑證上的名稱不符。"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"此憑證已過期。"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"此憑證尚未生效。"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"此憑證的日期無效。"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"此憑證無效。"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"不明的憑證錯誤。"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"安全性警告"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"查看憑證"</string>
+    <string name="ok" msgid="2817931639040794018">"確定"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"電郵地址:"</string>
+    <string name="page_info" msgid="4416941086705172545">"頁面資料"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml b/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml
index 2a2e397..9f92f39 100644
--- a/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"你嘗試加入的網路有安全問題。"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"例如,登入網頁中顯示的機構可能並非該網頁實際隸屬的機構。"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"透過瀏覽器繼續"</string>
-    <string name="ok" msgid="1509280796718850364">"確定"</string>
-    <string name="page_info" msgid="4048529256302257195">"頁面資訊"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"位址:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"安全性警告"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"檢視憑證"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"這個憑證並非來自信任的授權單位。"</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"網站名稱與憑證上的名稱不相符。"</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"此憑證已過期"</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"這個憑證尚未生效。"</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"這個憑證的日期無效。"</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"這個憑證無效。"</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"不明的憑證錯誤。"</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"這個憑證並非來自信任的授權單位。"</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"網站名稱與憑證上的名稱不相符。"</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"這個憑證已過期。"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"這個憑證尚未生效。"</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"這個憑證的日期無效。"</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"這個憑證無效。"</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"不明的憑證錯誤。"</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"安全性警告"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"查看憑證"</string>
+    <string name="ok" msgid="2817931639040794018">"確定"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"地址:"</string>
+    <string name="page_info" msgid="4416941086705172545">"頁面資訊"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-zu/strings.xml b/packages/CaptivePortalLogin/res/values-zu/strings.xml
index 7943645..ebb0f54 100644
--- a/packages/CaptivePortalLogin/res/values-zu/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zu/strings.xml
@@ -9,16 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Inethiwekhi ozama ukuyijoyina inezinkinga zokuvikela."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Isibonelo, ikhasi lokungena ngemvume kungenzeka lingelenhlangano ebonisiwe."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Qhubeka noma kunjalo ngesiphequluli"</string>
-    <string name="ok" msgid="1509280796718850364">"KULUNGILE"</string>
-    <string name="page_info" msgid="4048529256302257195">"Ulwazi lekhasi"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"Ikheli:"</string>
-    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Isexwayiso sokuvikeleka"</string>
-    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Buka isitifiketi"</string>
-    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Lesi sitifiketi asiphumi embusweni othembekile."</string>
-    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Igama lale ngosi alifani negama elikusitifiketi."</string>
-    <string name="ssl_error_expired" msgid="5739349389499575559">"Lesi sitifiketi siphelelwe yisikhathi"</string>
-    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Lesi sitifiketi asilungile okwamanje"</string>
-    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Lesi sitifiketi sinosuku olungalungile."</string>
-    <string name="ssl_error_invalid" msgid="9041704741505449967">"Lesi sitifiketi asilungile."</string>
-    <string name="ssl_error_unknown" msgid="5679243486524754571">"Iphutha lesitifiketi elingaziwa."</string>
+    <string name="ssl_error_untrusted" msgid="1496280318271264520">"Lesi sitifiketi asisuki kusiphathimandla esithembekile."</string>
+    <string name="ssl_error_mismatch" msgid="3060364165934822383">"Igama lesayithi alifani negama elikusitifiketi."</string>
+    <string name="ssl_error_expired" msgid="1501588340716182495">"Lesi sitifiketi siphelelwe yisikhathi"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8648649030525886924">"Lesi sitifiketi asivumelekile okwamanje."</string>
+    <string name="ssl_error_date_invalid" msgid="88425990680059223">"Lesi sitifiketi sinosuku olungalungile."</string>
+    <string name="ssl_error_invalid" msgid="2540546515565633432">"Lesi sitifiketi asilungile."</string>
+    <string name="ssl_error_unknown" msgid="4405203446079465859">"Iphutha lesitifiketi elingaziwa."</string>
+    <string name="ssl_security_warning_title" msgid="8768539813847504404">"Isexwayiso sokuvikeleka"</string>
+    <string name="ssl_error_view_certificate" msgid="5722652540168339333">"Buka isitifiketi"</string>
+    <string name="ok" msgid="2817931639040794018">"KULUNGILE"</string>
+    <string name="page_info_address" msgid="1261481517455692363">"Ikheli:"</string>
+    <string name="page_info" msgid="4416941086705172545">"Ulwazi lekhasi"</string>
 </resources>
diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 12df263..1737b64 100644
--- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -26,7 +26,6 @@
 import android.car.Car;
 import android.car.CarNotConnectedException;
 import android.car.media.CarAudioManager;
-import android.car.media.ICarVolumeCallback;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -106,9 +105,16 @@
     private ListItemAdapter mPagedListAdapter;
     private Car mCar;
     private CarAudioManager mCarAudioManager;
-    private final ICarVolumeCallback mVolumeChangeCallback = new ICarVolumeCallback.Stub() {
+    private final CarAudioManager.CarVolumeCallback mVolumeChangeCallback =
+            new CarAudioManager.CarVolumeCallback() {
         @Override
-        public void onGroupVolumeChanged(int groupId, int flags) {
+        public void onGroupVolumeChanged(int zoneId, int groupId, int flags) {
+            // TODO: Include zoneId into consideration.
+            // For instance
+            // - single display + single-zone, ignore zoneId
+            // - multi-display + single-zone, zoneId is fixed, may show volume bar on all displays
+            // - single-display + multi-zone, may show volume bar on primary display only
+            // - multi-display + multi-zone, may show volume bar on display specified by zoneId
             VolumeItem volumeItem = mAvailableVolumeItems.get(groupId);
             int value = getSeekbarValue(mCarAudioManager, groupId);
             // Do not update the progress if it is the same as before. When car audio manager sets
@@ -124,7 +130,7 @@
         }
 
         @Override
-        public void onMasterMuteChanged(int flags) {
+        public void onMasterMuteChanged(int zoneId, int flags) {
             // ignored
         }
     };
@@ -156,7 +162,7 @@
                 if (mPagedListAdapter != null) {
                     mPagedListAdapter.notifyDataSetChanged();
                 }
-                mCarAudioManager.registerVolumeCallback(mVolumeChangeCallback.asBinder());
+                mCarAudioManager.registerCarVolumeCallback(mVolumeChangeCallback);
             } catch (CarNotConnectedException e) {
                 Log.e(TAG, "Car is not connected!", e);
             }
@@ -434,11 +440,7 @@
     }
 
     private void cleanupAudioManager() {
-        try {
-            mCarAudioManager.unregisterVolumeCallback(mVolumeChangeCallback.asBinder());
-        } catch (CarNotConnectedException e) {
-            Log.e(TAG, "Car is not connected!", e);
-        }
+        mCarAudioManager.unregisterCarVolumeCallback(mVolumeChangeCallback);
         mVolumeLineItems.clear();
         mCarAudioManager = null;
     }
diff --git a/packages/PackageInstaller/res/values-as/strings.xml b/packages/PackageInstaller/res/values-as/strings.xml
index 172e031..2f2d867 100644
--- a/packages/PackageInstaller/res/values-as/strings.xml
+++ b/packages/PackageInstaller/res/values-as/strings.xml
@@ -16,150 +16,78 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_name (7488448184431507488) -->
-    <skip />
-    <!-- no translation found for install (711829760615509273) -->
-    <skip />
-    <!-- no translation found for done (6632441120016885253) -->
-    <skip />
-    <!-- no translation found for cancel (1018267193425558088) -->
-    <skip />
-    <!-- no translation found for installing (4921993079741206516) -->
-    <skip />
-    <!-- no translation found for installing_app (1165095864863849422) -->
-    <skip />
-    <!-- no translation found for install_done (5987363587661783896) -->
-    <skip />
-    <!-- no translation found for install_confirm_question (8176284075816604590) -->
-    <skip />
-    <!-- no translation found for install_confirm_question_update (7942235418781274635) -->
-    <skip />
-    <!-- no translation found for install_confirm_question_update_system (4713001702777910263) -->
-    <skip />
-    <!-- no translation found for install_failed (5777824004474125469) -->
-    <skip />
-    <!-- no translation found for install_failed_blocked (8512284352994752094) -->
-    <skip />
-    <!-- no translation found for install_failed_conflict (3493184212162521426) -->
-    <skip />
-    <!-- no translation found for install_failed_incompatible (6019021440094927928) -->
-    <skip />
-    <!-- no translation found for install_failed_incompatible (2890001324362291683) -->
-    <skip />
-    <!-- no translation found for install_failed_incompatible (7254630419511645826) -->
-    <skip />
-    <!-- no translation found for install_failed_invalid_apk (8581007676422623930) -->
-    <skip />
-    <!-- no translation found for install_failed_msg (6298387264270562442) -->
-    <skip />
-    <!-- no translation found for install_failed_msg (1920009940048975221) -->
-    <skip />
-    <!-- no translation found for install_failed_msg (6484461562647915707) -->
-    <skip />
-    <!-- no translation found for launch (3952550563999890101) -->
-    <skip />
-    <!-- no translation found for unknown_apps_admin_dlg_text (4456572224020176095) -->
-    <skip />
-    <!-- no translation found for unknown_apps_user_restriction_dlg_text (151020786933988344) -->
-    <skip />
-    <!-- no translation found for install_apps_user_restriction_dlg_text (2154119597001074022) -->
-    <skip />
-    <!-- no translation found for ok (7871959885003339302) -->
-    <skip />
-    <!-- no translation found for manage_applications (5400164782453975580) -->
-    <skip />
-    <!-- no translation found for out_of_space_dlg_title (4156690013884649502) -->
-    <skip />
-    <!-- no translation found for out_of_space_dlg_text (8727714096031856231) -->
-    <skip />
-    <!-- no translation found for app_not_found_dlg_title (5107924008597470285) -->
-    <skip />
-    <!-- no translation found for app_not_found_dlg_text (5219983779377811611) -->
-    <skip />
-    <!-- no translation found for user_is_not_allowed_dlg_title (6915293433252210232) -->
-    <skip />
-    <!-- no translation found for user_is_not_allowed_dlg_text (3468447791330611681) -->
-    <skip />
-    <!-- no translation found for generic_error_dlg_title (5863195085927067752) -->
-    <skip />
-    <!-- no translation found for generic_error_dlg_text (5287861443265795232) -->
-    <skip />
-    <!-- no translation found for uninstall_application_title (4045420072401428123) -->
-    <skip />
-    <!-- no translation found for uninstall_update_title (824411791011583031) -->
-    <skip />
-    <!-- no translation found for uninstall_activity_text (1928194674397770771) -->
-    <skip />
-    <!-- no translation found for uninstall_application_text (3816830743706143980) -->
-    <skip />
-    <!-- no translation found for uninstall_application_text_all_users (575491774380227119) -->
-    <skip />
-    <!-- no translation found for uninstall_application_text_user (498072714173920526) -->
-    <skip />
-    <!-- no translation found for uninstall_update_text (863648314632448705) -->
-    <skip />
-    <!-- no translation found for uninstall_update_text_multiuser (8992883151333057227) -->
-    <skip />
-    <!-- no translation found for uninstalling_notification_channel (840153394325714653) -->
-    <skip />
-    <!-- no translation found for uninstall_failure_notification_channel (1136405866767576588) -->
-    <skip />
-    <!-- no translation found for uninstalling (8709566347688966845) -->
-    <skip />
-    <!-- no translation found for uninstalling_app (8866082646836981397) -->
-    <skip />
-    <!-- no translation found for uninstall_done (439354138387969269) -->
-    <skip />
-    <!-- no translation found for uninstall_done_app (4588850984473605768) -->
-    <skip />
-    <!-- no translation found for uninstall_failed (1847750968168364332) -->
-    <skip />
-    <!-- no translation found for uninstall_failed_app (5506028705017601412) -->
-    <skip />
-    <!-- no translation found for uninstall_failed_device_policy_manager (785293813665540305) -->
-    <skip />
-    <!-- no translation found for uninstall_failed_device_policy_manager_of_user (4813104025494168064) -->
-    <skip />
-    <!-- no translation found for uninstall_all_blocked_profile_owner (2009393666026751501) -->
-    <skip />
-    <!-- no translation found for uninstall_blocked_profile_owner (6373897407002404848) -->
-    <skip />
-    <!-- no translation found for uninstall_blocked_device_owner (6724602931761073901) -->
-    <skip />
-    <!-- no translation found for manage_device_administrators (3092696419363842816) -->
-    <skip />
-    <!-- no translation found for manage_users (1243995386982560813) -->
-    <skip />
-    <!-- no translation found for uninstall_failed_msg (2176744834786696012) -->
-    <skip />
-    <!-- no translation found for Parse_error_dlg_text (1661404001063076789) -->
-    <skip />
-    <!-- no translation found for wear_not_allowed_dlg_title (8664785993465117517) -->
-    <skip />
-    <!-- no translation found for wear_not_allowed_dlg_text (704615521550939237) -->
-    <skip />
-    <!-- no translation found for message_staging (8032722385658438567) -->
-    <skip />
-    <!-- no translation found for app_name_unknown (6881210203354323926) -->
-    <skip />
-    <!-- no translation found for untrusted_external_source_warning (6539403649459942547) -->
-    <skip />
-    <!-- no translation found for untrusted_external_source_warning (1206648674551321364) -->
-    <skip />
-    <!-- no translation found for untrusted_external_source_warning (7279739265754475165) -->
-    <skip />
-    <!-- no translation found for anonymous_source_warning (2784902545920822500) -->
-    <skip />
-    <!-- no translation found for anonymous_source_warning (3939101621438855516) -->
-    <skip />
-    <!-- no translation found for anonymous_source_warning (5599483539528168566) -->
-    <skip />
-    <!-- no translation found for anonymous_source_continue (4375745439457209366) -->
-    <skip />
-    <!-- no translation found for external_sources_settings (4046964413071713807) -->
-    <skip />
-    <!-- no translation found for wear_app_channel (1960809674709107850) -->
-    <skip />
+    <string name="app_name" msgid="7488448184431507488">"পেকেজ ইনষ্টলাৰ"</string>
+    <string name="install" msgid="711829760615509273">"ইনষ্টল কৰক"</string>
+    <string name="done" msgid="6632441120016885253">"সম্পন্ন হ’ল"</string>
+    <string name="cancel" msgid="1018267193425558088">"বাতিল কৰক"</string>
+    <string name="installing" msgid="4921993079741206516">"ইনষ্টল কৰি থকা হৈছে…"</string>
+    <string name="installing_app" msgid="1165095864863849422">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ইনষ্টল কৰি থকা হৈছে…"</string>
+    <string name="install_done" msgid="5987363587661783896">"এপ্ ইনষ্টল কৰা হ\'ল।"</string>
+    <string name="install_confirm_question" msgid="8176284075816604590">"আপুনি এই এপ্লিকেশ্বনটো ইনষ্টল কৰিব বিচাৰেনে?"</string>
+    <string name="install_confirm_question_update" msgid="7942235418781274635">"আপুনি আগৰে পৰা থকা এপ্লিকেশ্বন আপডে\'ট কৰিব বিচাৰেনে? আপোনাৰ আগৰ ডেটা নেহেৰায়।"</string>
+    <string name="install_confirm_question_update_system" msgid="4713001702777910263">"আপুনি এই আগৰে পৰা থকা এপ্লিকেশ্বনটো আপডে\'ট কৰিব বিচাৰেনে? আপোনাৰ আগৰ ডেটা নেহেৰায়।"</string>
+    <string name="install_failed" msgid="5777824004474125469">"এপ্ ইনষ্টল কৰা হোৱা নাই।"</string>
+    <string name="install_failed_blocked" msgid="8512284352994752094">"পেকেজটোৰ ইনষ্টল অৱৰোধ কৰা হৈছে।"</string>
+    <string name="install_failed_conflict" msgid="3493184212162521426">"এপটো ইনষ্টল কৰিব পৰা নগ\'ল কাৰণ ইয়াৰ সৈতে আগৰে পৰা থকা এটা পেকেজৰ সংঘাত হৈছে।"</string>
+    <string name="install_failed_incompatible" product="tablet" msgid="6019021440094927928">"আপোনাৰ টেবলেটৰ সৈতে খাপ নোখোৱাৰ বাবে এপটো ইনষ্টল কৰা নহ\'ল।"</string>
+    <string name="install_failed_incompatible" product="tv" msgid="2890001324362291683">"আপোনাৰ টিভিত এই এপটো নচলে"</string>
+    <string name="install_failed_incompatible" product="default" msgid="7254630419511645826">"আপোনাৰ ফ\'নৰ সৈতে খাপ নোখোৱাৰ বাবে এপটো ইনষ্টল কৰা নহ\'ল।"</string>
+    <string name="install_failed_invalid_apk" msgid="8581007676422623930">"পেকেজটো মান্য নোহোৱাৰ বাবে এপটো ইনষ্টল কৰা নহ\'ল।"</string>
+    <string name="install_failed_msg" product="tablet" msgid="6298387264270562442">"আপোনাৰ টে\'বলেটত <xliff:g id="APP_NAME">%1$s</xliff:g> ইনষ্টল কৰিব পৰা নগ\'ল৷"</string>
+    <string name="install_failed_msg" product="tv" msgid="1920009940048975221">"আপোনাৰ টিভিত <xliff:g id="APP_NAME">%1$s</xliff:g> ইনষ্টল কৰিব পৰা নগ\'ল।"</string>
+    <string name="install_failed_msg" product="default" msgid="6484461562647915707">"আপোনাৰ ফ\'নত <xliff:g id="APP_NAME">%1$s</xliff:g> ইনষ্টল কৰিব পৰা নগ\'ল৷"</string>
+    <string name="launch" msgid="3952550563999890101">"খোলক"</string>
+    <string name="unknown_apps_admin_dlg_text" msgid="4456572224020176095">"আপোনাৰ প্ৰশাসকে অজ্ঞাত উৎসৰ পৰা পোৱা এপ্ ইনষ্টল কৰাৰ অনুমতি দিয়া নাই"</string>
+    <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"এই ব্যৱহাৰকাৰীয়ে অজ্ঞাত উৎসৰপৰা পোৱা এপসমূহ ইনষ্টল কৰিব নোৱাৰে"</string>
+    <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"এই ব্যৱহাৰকাৰীজনৰ এপ্ ইনষ্টল কৰাৰ অনুমতি নাই"</string>
+    <string name="ok" msgid="7871959885003339302">"ঠিক আছে"</string>
+    <string name="manage_applications" msgid="5400164782453975580">"এপ্ পৰিচালনা"</string>
+    <string name="out_of_space_dlg_title" msgid="4156690013884649502">"খালী ঠাই নাই"</string>
+    <string name="out_of_space_dlg_text" msgid="8727714096031856231">"<xliff:g id="APP_NAME">%1$s</xliff:g> ইনষ্টল কৰিব পৰা নগ\'ল। কিছু খালী ঠাই উলিয়াই আকৌ চেষ্টা কৰক৷"</string>
+    <string name="app_not_found_dlg_title" msgid="5107924008597470285">"এপটো পোৱা নগ\'ল"</string>
+    <string name="app_not_found_dlg_text" msgid="5219983779377811611">"ইনষ্টল কৰি ৰখা এপৰ তালিকাত এই এপটো পোৱা নগ\'ল।"</string>
+    <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"অনুমতি নাই"</string>
+    <string name="user_is_not_allowed_dlg_text" msgid="3468447791330611681">"বর্তমানৰ ব্যৱহাৰকাৰীজনক এইটো আনইনষ্টল কৰিবলৈ অনুমতি দিয়া হোৱা নাই।"</string>
+    <string name="generic_error_dlg_title" msgid="5863195085927067752">"আসোঁৱাহ"</string>
+    <string name="generic_error_dlg_text" msgid="5287861443265795232">"এপ্ আনইনষ্টল কৰিব পৰা নগ\'ল।"</string>
+    <string name="uninstall_application_title" msgid="4045420072401428123">"এপ্ আনইনষ্টল কৰক"</string>
+    <string name="uninstall_update_title" msgid="824411791011583031">"আপডে\'ট আনইনষ্টল কৰক"</string>
+    <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> হৈছে তলৰ এপটোৰ এটা অংশ:"</string>
+    <string name="uninstall_application_text" msgid="3816830743706143980">"আপুনি এই এপটো আনইনষ্টল কৰিব বিচাৰেনে?"</string>
+    <string name="uninstall_application_text_all_users" msgid="575491774380227119">"আপুনি "<b>"সকলো"</b>" ব্যৱহাৰকাৰীৰ বাবে এই এপটো আনইনষ্টল কৰিব বিচাৰেনে? এপ্লিকেশ্বন আৰু ইয়াৰ ডেটা ডিভাইচটোত থকা "<b>"সকলো"</b>" ব্যৱহাৰকাৰীৰ পৰা আঁতৰোৱা হ\'ব৷"</string>
+    <string name="uninstall_application_text_user" msgid="498072714173920526">"আপুনি ব্যৱহাৰকাৰীৰ <xliff:g id="USERNAME">%1$s</xliff:g> বাবে এই এপটো আনইনষ্টল কৰিব বিচাৰেনে?"</string>
+    <string name="uninstall_update_text" msgid="863648314632448705">"এই এপটোৰ ফেক্টৰী সংস্কৰণ ব্যৱহাৰ কৰিব বিচাৰেনে? সকলো ডেটা মচা হ\'ব।"</string>
+    <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"এই এপটোৰ ফেক্টৰী সংস্কৰণ ব্যৱহাৰ কৰিব বিচাৰেনে? সকলো ডেটা মচা হ\'ব। কর্মস্থানৰ প্ৰফাইল থকা ব্যৱহাৰকাৰীৰ লগতে ডিভাইচটোৰ সকলো ব্যৱহাৰকাৰীৰ ওপৰত ইয়াৰ প্ৰভাৱ পৰিব।"</string>
+    <string name="uninstalling_notification_channel" msgid="840153394325714653">"আনইনষ্টল কৰি থকা হৈছে"</string>
+    <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"যিবোৰ আনইনষ্টল পৰা নগ\'ল"</string>
+    <string name="uninstalling" msgid="8709566347688966845">"আনইনষ্টল কৰি থকা হৈছে…"</string>
+    <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> আনইনষ্টল কৰি থকা হৈছে…"</string>
+    <string name="uninstall_done" msgid="439354138387969269">"আনইনষ্টল কৰা হ’ল।"</string>
+    <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> আনইনষ্টল কৰা হ\'ল"</string>
+    <string name="uninstall_failed" msgid="1847750968168364332">"আনইনষ্টল কৰিব পৰা নগ\'ল।"</string>
+    <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> আনইনষ্টল কৰিব পৰা নগ\'ল।"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="785293813665540305">"ডিভাইচৰ সক্ৰিয় প্ৰশাসক এপ্ আনইনষ্টল কৰিব নোৱাৰি"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="4813104025494168064">"<xliff:g id="USERNAME">%1$s</xliff:g>ৰ সক্ৰিয় ডিভাইচৰ প্ৰশাসকীয় এপ্ আনইনষ্টল কৰিব নোৱাৰি"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="2009393666026751501">"এই এপটো কিছুসংখ্যক ব্যৱহাৰকাৰী বা প্ৰ\'ফাইলৰ বাবে প্ৰয়োজনীয় আৰু বাকীসকলৰ বাবে ইয়াক আনইনষ্টল কৰা হৈছে"</string>
+    <string name="uninstall_blocked_profile_owner" msgid="6373897407002404848">"আপোনাৰ প্ৰ\'ফাইলৰ বাবে এই এপটোৰ প্ৰয়োজন আছে গতিকে আনইনষ্টল কৰিব পৰা নাযায়।"</string>
+    <string name="uninstall_blocked_device_owner" msgid="6724602931761073901">"এই এপটো আনইনষ্টল কৰিব পৰা নাযায় কাৰণ আপোনাৰ ডিভাইচৰ প্ৰশাসকে এই এপ্ ৰখাটো বাধ্যতামূলক কৰি ৰাখিছে।"</string>
+    <string name="manage_device_administrators" msgid="3092696419363842816">"ডিভাইচৰ প্ৰশাসক এপসমূহ পৰিচালনা কৰক"</string>
+    <string name="manage_users" msgid="1243995386982560813">"ব্যৱহাৰকাৰী পৰিচালনা কৰক"</string>
+    <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> আনইনষ্টল কৰিব নোৱাৰি।"</string>
+    <string name="Parse_error_dlg_text" msgid="1661404001063076789">"পেকেজটো পাৰ্ছ কৰোঁতে এটা সমস্যাই দেখা দিছিল।"</string>
+    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android ৱেৰ"</string>
+    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"ৱেৰ-ত ইনষ্টল/আনইনষ্টল কৰিব পৰা নাযায়।"</string>
+    <string name="message_staging" msgid="8032722385658438567">"এপৰ অন্তিম পর্যায়ৰ পৰীক্ষণ চলি আছে…"</string>
+    <string name="app_name_unknown" msgid="6881210203354323926">"অজ্ঞাত"</string>
+    <string name="untrusted_external_source_warning" product="tablet" msgid="6539403649459942547">"আপোনাৰ সুৰক্ষাৰ বাবে এই উৎসৰ পৰা অজ্ঞাত এপসমূহ আপোনাৰ টেবলেটত ইনষ্টল কৰাৰ অনুমতি দিয়া হোৱা নাই।"</string>
+    <string name="untrusted_external_source_warning" product="tv" msgid="1206648674551321364">"আপোনাৰ সুৰক্ষাৰ বাবে এই উৎসৰ পৰা অজ্ঞাত এপসমূহ আপোনাৰ টিভিত ইনষ্টল কৰাৰ অনুমতি দিয়া হোৱা নাই।"</string>
+    <string name="untrusted_external_source_warning" product="default" msgid="7279739265754475165">"আপোনাৰ সুৰক্ষাৰ বাবে এই উৎসৰ পৰা অজ্ঞাত এপসমূহ আপোনাৰ ফ\'নত ইনষ্টল কৰাৰ অনুমতি দিয়া হোৱা নাই।"</string>
+    <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"আপোনাৰ ফ\'ন আৰু ব্যক্তিগত ডেটা অজ্ঞাত এপৰ আক্ৰমণৰ বলি হোৱাৰ সম্ভাৱনা অধিক। আপুনি এই এপটো ইনষ্টল কৰি এপটোৰ ব্যৱহাৰৰ ফলত আপোনাৰ টিভিত হ\'ব পৰা যিকোনো ক্ষতি বা ডেটা ক্ষয়ৰ বাবে আপুনি নিজে দায়ী হ\'ব বুলি সন্মতি দিয়ে।"</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"আপোনাৰ টেবলেট আৰু ব্যক্তিগত ডেটা অজ্ঞাত এপৰ আক্ৰমণৰ বলি হোৱাৰ সম্ভাৱনা অধিক। আপুনি এই এপটো ইনষ্টল কৰি এপটোৰ ব্যৱহাৰৰ ফলত আপোনাৰ টিভিত হ\'ব পৰা যিকোনো ক্ষতি বা ডেটা ক্ষয়ৰ বাবে আপুনি নিজে দায়ী হ\'ব বুলি সন্মতি দিয়ে।"</string>
+    <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"আপোনাৰ টিভি আৰু ব্যক্তিগত ডেটা অজ্ঞাত এপৰ আক্ৰমণৰ বলি হোৱাৰ সম্ভাৱনা অধিক। আপুনি এই এপটো ইনষ্টল কৰি এপটোৰ ব্যৱহাৰৰ ফলত আপোনাৰ টিভিত হ\'ব পৰা যিকোনো ক্ষতি বা ডেটা ক্ষয়ৰ বাবে আপুনি নিজে দায়ী হ\'ব বুলি সন্মতি দিয়ে।"</string>
+    <string name="anonymous_source_continue" msgid="4375745439457209366">"অব্যাহত ৰাখক"</string>
+    <string name="external_sources_settings" msgid="4046964413071713807">"ছেটিংসমূহ"</string>
+    <string name="wear_app_channel" msgid="1960809674709107850">"ৱেৰ এপসমূহ ইনষ্টল/আনইনষ্টল কৰি থকা হৈছে"</string>
     <string name="app_installed_notification_channel_description" msgid="2695385797601574123">"এপ্ ইনষ্টল কৰাৰ জাননী"</string>
     <string name="notification_installation_success_message" msgid="6450467996056038442">"সফলতাৰে ইনষ্টল কৰা হ’ল"</string>
     <string name="notification_installation_success_status" msgid="3172502643504323321">"“<xliff:g id="APPNAME">%1$s</xliff:g>” সফলতাৰে ইনষ্টল কৰা হ’ল"</string>
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 03eafc4..478ee54 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -51,6 +51,7 @@
     <application
         android:allowClearUserData="true"
         android:label="@string/app_label"
+        android:icon="@drawable/ic_app_icon"
         android:supportsRtl="true">
 
         <service
diff --git a/packages/PrintSpooler/res/drawable/app_icon_foreground.xml b/packages/PrintSpooler/res/drawable/app_icon_foreground.xml
new file mode 100644
index 0000000..249e387
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable/app_icon_foreground.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<inset
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:insetTop="25%"
+    android:insetRight="25%"
+    android:insetBottom="25%"
+    android:insetLeft="25%">
+
+    <vector
+        android:width="36dp"
+        android:height="36dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+
+        <path
+            android:fillColor="#FFFFFF"
+            android:pathData="M19,8L5,8c-1.66,0 -3,1.34 -3,3v6h4v4h12v-4h4v-6c0,-1.66 -1.34,-3 -3,-3zM16,19L8,19v-5h8v5zM19,12c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1zM18,3L6,3v4h12L18,3z" />
+    </vector>
+</inset>
diff --git a/packages/PrintSpooler/res/drawable/ic_app_icon.xml b/packages/PrintSpooler/res/drawable/ic_app_icon.xml
new file mode 100644
index 0000000..82c18e0
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable/ic_app_icon.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@*android:color/accent_device_default_light"/>
+    <foreground android:drawable="@drawable/app_icon_foreground"/>
+</adaptive-icon>
\ No newline at end of file
diff --git a/packages/SettingsLib/SearchWidget/res/drawable/ic_search_24dp.xml b/packages/SettingsLib/SearchWidget/res/drawable/ic_search_24dp.xml
index 7e65848..a046332 100644
--- a/packages/SettingsLib/SearchWidget/res/drawable/ic_search_24dp.xml
+++ b/packages/SettingsLib/SearchWidget/res/drawable/ic_search_24dp.xml
@@ -20,7 +20,7 @@
         android:height="24dp"
         android:viewportWidth="24"
         android:viewportHeight="24"
-        android:tint="?android:attr/colorControlNormal">
+        android:tint="?android:attr/colorAccent">
     <path
         android:fillColor="#FF000000"
         android:pathData="M20.49,19l-5.73,-5.73C15.53,12.2 16,10.91 16,9.5C16,5.91 13.09,3 9.5,3S3,5.91 3,9.5C3,13.09 5.91,16 9.5,16c1.41,0 2.7,-0.47 3.77,-1.24L19,20.49L20.49,19zM5,9.5C5,7.01 7.01,5 9.5,5S14,7.01 14,9.5S11.99,14 9.5,14S5,11.99 5,9.5z"/>
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
index 1457fcf..74aaf3c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
@@ -38,6 +38,7 @@
 import android.text.Spanned;
 import android.text.style.ForegroundColorSpan;
 import android.text.style.ImageSpan;
+import android.util.Log;
 import android.view.MenuItem;
 import android.widget.TextView;
 
@@ -52,6 +53,9 @@
  * support message dialog.
  */
 public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
+
+    private static final String LOG_TAG = "RestrictedLockUtils";
+
     /**
      * @return drawables for displaying with settings that are locked by a device admin.
      */
@@ -305,6 +309,42 @@
         return null;
     }
 
+    /**
+     * @param userId user id of a managed profile.
+     * @return profile owner admin if cross profile calendar is disallowed.
+     */
+    public static EnforcedAdmin getCrossProfileCalendarEnforcingAdmin(Context context, int userId) {
+        final Context managedProfileContext = createPackageContextAsUser(
+                context, userId);
+        final DevicePolicyManager dpm = managedProfileContext.getSystemService(
+                DevicePolicyManager.class);
+        if (dpm == null) {
+            return null;
+        }
+        final EnforcedAdmin admin = getProfileOwner(context, userId);
+        if (admin == null) {
+            return null;
+        }
+        if (dpm.getCrossProfileCalendarPackages().isEmpty()) {
+            return admin;
+        }
+        return null;
+    }
+
+    /**
+     * @param userId user id of a managed profile.
+     * @return a context created from the given context for the given user, or null if it fails.
+     */
+    private static Context createPackageContextAsUser(Context context, int userId) {
+        try {
+            return context.createPackageContextAsUser(
+                    context.getPackageName(), 0 /* flags */, UserHandle.of(userId));
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(LOG_TAG, "Failed to create user context", e);
+        }
+        return null;
+    }
+
     public static EnforcedAdmin checkIfAccessibilityServiceDisallowed(Context context,
             String packageName, int userId) {
         DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 9270d13..1bffff7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -71,15 +71,8 @@
 
     boolean mJustDiscovered;
 
-    private int mMessageRejectionCount;
-
     private final Collection<Callback> mCallbacks = new ArrayList<>();
 
-    // How many times user should reject the connection to make the choice persist.
-    private final static int MESSAGE_REJECTION_COUNT_LIMIT_TO_PERSIST = 2;
-
-    private final static String MESSAGE_REJECTION_COUNT_PREFS_NAME = "bluetooth_message_reject";
-
     /**
      * Last time a bt profile auto-connect was attempted.
      * If an ACTION_UUID intent comes in within
@@ -348,7 +341,6 @@
         fetchActiveDevices();
         migratePhonebookPermissionChoice();
         migrateMessagePermissionChoice();
-        fetchMessageRejectionCount();
 
         dispatchAttributesChanged();
     }
@@ -642,8 +634,6 @@
             mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_UNKNOWN);
             mDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_UNKNOWN);
             mDevice.setSimAccessPermission(BluetoothDevice.ACCESS_UNKNOWN);
-            mMessageRejectionCount = 0;
-            saveMessageRejectionCount();
         }
 
         refresh();
@@ -797,34 +787,6 @@
         editor.commit();
     }
 
-    /**
-     * @return Whether this rejection should persist.
-     */
-    public boolean checkAndIncreaseMessageRejectionCount() {
-        if (mMessageRejectionCount < MESSAGE_REJECTION_COUNT_LIMIT_TO_PERSIST) {
-            mMessageRejectionCount++;
-            saveMessageRejectionCount();
-        }
-        return mMessageRejectionCount >= MESSAGE_REJECTION_COUNT_LIMIT_TO_PERSIST;
-    }
-
-    private void fetchMessageRejectionCount() {
-        SharedPreferences preference = mContext.getSharedPreferences(
-                MESSAGE_REJECTION_COUNT_PREFS_NAME, Context.MODE_PRIVATE);
-        mMessageRejectionCount = preference.getInt(mDevice.getAddress(), 0);
-    }
-
-    private void saveMessageRejectionCount() {
-        SharedPreferences.Editor editor = mContext.getSharedPreferences(
-                MESSAGE_REJECTION_COUNT_PREFS_NAME, Context.MODE_PRIVATE).edit();
-        if (mMessageRejectionCount == 0) {
-            editor.remove(mDevice.getAddress());
-        } else {
-            editor.putInt(mDevice.getAddress(), mMessageRejectionCount);
-        }
-        editor.commit();
-    }
-
     private void processPhonebookAccess() {
         if (mDevice.getBondState() != BluetoothDevice.BOND_BONDED) return;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 67cfe6b..91892ab 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -363,7 +363,8 @@
             return null;
         }
         try {
-            return provider.call(context.getPackageName(), method, uriString, null);
+            return provider.call(context.getPackageName(), uri.getAuthority(),
+                    method, uriString, null);
         } catch (RemoteException e) {
             return null;
         }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
new file mode 100644
index 0000000..3520918
--- /dev/null
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -0,0 +1,355 @@
+/*
+ * 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.providers.settings;
+
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.ActivityManager;
+import android.content.IContentProvider;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.ShellCommand;
+import android.provider.Settings;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Receives shell commands from the command line related to device config flags, and dispatches them
+ * to the SettingsProvider.
+ *
+ * @hide
+ */
+@SystemApi
+public final class DeviceConfigService extends Binder {
+    /**
+     * TODO(b/113100523): Move this to DeviceConfig.java when it is added, and expose it as a System
+     *     API.
+     */
+    private static final Uri CONFIG_CONTENT_URI =
+            Uri.parse("content://" + Settings.AUTHORITY + "/config");
+
+    final SettingsProvider mProvider;
+
+    public DeviceConfigService(SettingsProvider provider) {
+        mProvider = provider;
+    }
+
+    @Override
+    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+        (new MyShellCommand(mProvider)).exec(this, in, out, err, args, callback, resultReceiver);
+    }
+
+    static final class MyShellCommand extends ShellCommand {
+        final SettingsProvider mProvider;
+
+        enum CommandVerb {
+            UNSPECIFIED,
+            GET,
+            PUT,
+            DELETE,
+            LIST,
+            RESET,
+        }
+
+        MyShellCommand(SettingsProvider provider) {
+            mProvider = provider;
+        }
+
+        @Override
+        public int onCommand(String cmd) {
+            if (cmd == null || "help".equals(cmd) || "-h".equals(cmd)) {
+                onHelp();
+                return -1;
+            }
+
+            final PrintWriter perr = getErrPrintWriter();
+            boolean isValid = false;
+            CommandVerb verb;
+            if ("get".equalsIgnoreCase(cmd)) {
+                verb = CommandVerb.GET;
+            } else if ("put".equalsIgnoreCase(cmd)) {
+                verb = CommandVerb.PUT;
+            } else if ("delete".equalsIgnoreCase(cmd)) {
+                verb = CommandVerb.DELETE;
+            } else if ("list".equalsIgnoreCase(cmd)) {
+                verb = CommandVerb.LIST;
+                if (peekNextArg() == null) {
+                    isValid = true;
+                }
+            } else if ("reset".equalsIgnoreCase(cmd)) {
+                verb = CommandVerb.RESET;
+            } else {
+                // invalid
+                perr.println("Invalid command: " + cmd);
+                return -1;
+            }
+
+            int resetMode = -1;
+            boolean makeDefault = false;
+            String namespace = null;
+            String key = null;
+            String value = null;
+            String arg = null;
+            while ((arg = getNextArg()) != null) {
+                if (verb == CommandVerb.RESET) {
+                    if (resetMode == -1) {
+                        if ("untrusted_defaults".equalsIgnoreCase(arg)) {
+                            resetMode = Settings.RESET_MODE_UNTRUSTED_DEFAULTS;
+                        } else if ("untrusted_clear".equalsIgnoreCase(arg)) {
+                            resetMode = Settings.RESET_MODE_UNTRUSTED_CHANGES;
+                        } else if ("trusted_defaults".equalsIgnoreCase(arg)) {
+                            resetMode = Settings.RESET_MODE_TRUSTED_DEFAULTS;
+                        } else {
+                            // invalid
+                            perr.println("Invalid reset mode: " + arg);
+                            return -1;
+                        }
+                        if (peekNextArg() == null) {
+                            isValid = true;
+                        }
+                    } else {
+                        namespace = arg;
+                        if (peekNextArg() == null) {
+                            isValid = true;
+                        } else {
+                            // invalid
+                            perr.println("Too many arguments");
+                            return -1;
+                        }
+                    }
+                } else if (namespace == null) {
+                    namespace = arg;
+                    if (verb == CommandVerb.LIST) {
+                        if (peekNextArg() == null) {
+                            isValid = true;
+                        } else {
+                            // invalid
+                            perr.println("Too many arguments");
+                            return -1;
+                        }
+                    }
+                } else if (key == null) {
+                    key = arg;
+                    if ((verb == CommandVerb.GET || verb == CommandVerb.DELETE)) {
+                        if (peekNextArg() == null) {
+                            isValid = true;
+                        } else {
+                            // invalid
+                            perr.println("Too many arguments");
+                            return -1;
+                        }
+                    }
+                } else if (value == null) {
+                    value = arg;
+                    if (verb == CommandVerb.PUT && peekNextArg() == null) {
+                        isValid = true;
+                    }
+                } else if ("default".equalsIgnoreCase(arg)) {
+                    makeDefault = true;
+                    if (verb == CommandVerb.PUT && peekNextArg() == null) {
+                        isValid = true;
+                    } else {
+                        // invalid
+                        perr.println("Too many arguments");
+                        return -1;
+                    }
+                }
+            }
+
+            if (!isValid) {
+                perr.println("Bad arguments");
+                return -1;
+            }
+
+            final IContentProvider iprovider = mProvider.getIContentProvider();
+            final PrintWriter pout = getOutPrintWriter();
+            switch (verb) {
+                case GET:
+                    pout.println(get(iprovider, namespace, key));
+                    break;
+                case PUT:
+                    put(iprovider, namespace, key, value, makeDefault);
+                    break;
+                case DELETE:
+                    pout.println(delete(iprovider, namespace, key)
+                            ? "Successfully deleted " + key + " from " + namespace
+                            : "Failed to delete " + key + " from " + namespace);
+                    break;
+                case LIST:
+                    for (String line : list(iprovider, namespace)) {
+                        pout.println(line);
+                    }
+                    break;
+                case RESET:
+                    reset(iprovider, resetMode, namespace);
+                    break;
+                default:
+                    perr.println("Unspecified command");
+                    return -1;
+            }
+            return 0;
+        }
+
+        @Override
+        public void onHelp() {
+            PrintWriter pw = getOutPrintWriter();
+            pw.println("Device Config (device_config) commands:");
+            pw.println("  help");
+            pw.println("      Print this help text.");
+            pw.println("  get NAMESPACE KEY");
+            pw.println("      Retrieve the current value of KEY from the given NAMESPACE.");
+            pw.println("  put NAMESPACE KEY VALUE [default]");
+            pw.println("      Change the contents of KEY to VALUE for the given NAMESPACE.");
+            pw.println("      {default} to set as the default value.");
+            pw.println("  delete NAMESPACE KEY");
+            pw.println("      Delete the entry for KEY for the given NAMESPACE.");
+            pw.println("  list [NAMESPACE]");
+            pw.println("      Print all keys and values defined, optionally for the given "
+                    + "NAMESPACE.");
+            pw.println("  reset RESET_MODE [NAMESPACE]");
+            pw.println("      Reset all flag values, optionally for a NAMESPACE, according to "
+                    + "RESET_MODE.");
+            pw.println("      RESET_MODE is one of {untrusted_defaults, untrusted_clear, "
+                    + "trusted_defaults}");
+            pw.println("      NAMESPACE limits which flags are reset if provided, otherwise all "
+                    + "flags are reset");
+        }
+
+        private String get(IContentProvider provider, String namespace, String key) {
+            String compositeKey = namespace + "/" + key;
+            String result = null;
+            try {
+                Bundle args = new Bundle();
+                args.putInt(Settings.CALL_METHOD_USER_KEY,
+                        ActivityManager.getService().getCurrentUser().id);
+                Bundle b = provider.call(resolveCallingPackage(), Settings.CALL_METHOD_GET_CONFIG,
+                        compositeKey, args);
+                if (b != null) {
+                    result = b.getPairValue();
+                }
+            } catch (RemoteException e) {
+                throw new RuntimeException("Failed in IPC", e);
+            }
+            return result;
+        }
+
+        private void put(IContentProvider provider, String namespace, String key, String value,
+                boolean makeDefault) {
+            String compositeKey = namespace + "/" + key;
+
+            try {
+                Bundle args = new Bundle();
+                args.putString(Settings.NameValueTable.VALUE, value);
+                args.putInt(Settings.CALL_METHOD_USER_KEY,
+                        ActivityManager.getService().getCurrentUser().id);
+                if (makeDefault) {
+                    args.putBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY, true);
+                }
+                provider.call(resolveCallingPackage(), Settings.CALL_METHOD_PUT_CONFIG,
+                        compositeKey, args);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Failed in IPC", e);
+            }
+        }
+
+        private boolean delete(IContentProvider provider, String namespace, String key) {
+            String compositeKey = namespace + "/" + key;
+            boolean success;
+
+            try {
+                Bundle args = new Bundle();
+                args.putInt(Settings.CALL_METHOD_USER_KEY,
+                        ActivityManager.getService().getCurrentUser().id);
+                Bundle b = provider.call(resolveCallingPackage(),
+                        Settings.CALL_METHOD_DELETE_CONFIG, compositeKey, args);
+                success = (b != null && b.getInt(SettingsProvider.RESULT_ROWS_DELETED) == 1);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Failed in IPC", e);
+            }
+            return success;
+        }
+
+        private List<String> list(IContentProvider provider, @Nullable String namespace) {
+            final ArrayList<String> lines = new ArrayList<>();
+
+            try {
+                Bundle args = new Bundle();
+                args.putInt(Settings.CALL_METHOD_USER_KEY,
+                        ActivityManager.getService().getCurrentUser().id);
+                if (namespace != null) {
+                    args.putString(Settings.CALL_METHOD_PREFIX_KEY, namespace);
+                }
+                Bundle b = provider.call(resolveCallingPackage(),
+                        Settings.CALL_METHOD_LIST_CONFIG, null, args);
+                if (b != null) {
+                    Map<String, String> flagsToValues =
+                            (HashMap) b.getSerializable(Settings.NameValueTable.VALUE);
+                    for (String key : flagsToValues.keySet()) {
+                        lines.add(key + "=" + flagsToValues.get(key));
+                    }
+                }
+
+                Collections.sort(lines);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Failed in IPC", e);
+            }
+            return lines;
+        }
+
+        private void reset(IContentProvider provider, int resetMode, @Nullable String namespace) {
+            try {
+                Bundle args = new Bundle();
+                args.putInt(Settings.CALL_METHOD_USER_KEY,
+                        ActivityManager.getService().getCurrentUser().id);
+                args.putInt(Settings.CALL_METHOD_RESET_MODE_KEY, resetMode);
+                args.putString(Settings.CALL_METHOD_PREFIX_KEY, namespace);
+                provider.call(
+                        resolveCallingPackage(), Settings.CALL_METHOD_RESET_CONFIG, null, args);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Failed in IPC", e);
+            }
+        }
+
+        private static String resolveCallingPackage() {
+            switch (Binder.getCallingUid()) {
+                case Process.ROOT_UID: {
+                    return "root";
+                }
+
+                case Process.SHELL_UID: {
+                    return "com.android.shell";
+                }
+
+                default: {
+                    return null;
+                }
+            }
+        }
+    }
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index df5b146..e3d3d81 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -208,9 +208,14 @@
                 GlobalSettingsProto.Autofill.MAX_VISIBLE_DATASETS);
         p.end(autofillToken);
 
+        final long backupToken = p.start(GlobalSettingsProto.BACKUP);
         dumpSetting(s, p,
                 Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS,
-                GlobalSettingsProto.BACKUP_AGENT_TIMEOUT_PARAMETERS);
+                GlobalSettingsProto.Backup.BACKUP_AGENT_TIMEOUT_PARAMETERS);
+        dumpSetting(s, p,
+                Settings.Global.BACKUP_MULTI_USER_ENABLED,
+                GlobalSettingsProto.Backup.BACKUP_MULTI_USER_ENABLED);
+        p.end(backupToken);
 
         final long batteryToken = p.start(GlobalSettingsProto.BATTERY);
         dumpSetting(s, p,
@@ -418,6 +423,12 @@
                 Settings.Global.CONTACTS_DATABASE_WAL_ENABLED,
                 GlobalSettingsProto.CONTACTS_DATABASE_WAL_ENABLED);
 
+        final long contentCaptureToken = p.start(GlobalSettingsProto.CONTENT_CAPTURE);
+        dumpSetting(s, p,
+                Settings.Global.CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED,
+                GlobalSettingsProto.ContentCapture.SERVICE_EXPLICITLY_ENABLED);
+        p.end(contentCaptureToken);
+
         final long dataToken = p.start(GlobalSettingsProto.DATA);
         // Settings.Global.DEFAULT_RESTRICT_BACKGROUND_DATA intentionally excluded.
         dumpSetting(s, p,
@@ -679,8 +690,14 @@
                 Settings.Global.GPU_DEBUG_LAYERS,
                 GlobalSettingsProto.Gpu.DEBUG_LAYERS);
         dumpSetting(s, p,
-                Settings.Global.ANGLE_ENABLED_APP,
-                GlobalSettingsProto.Gpu.ANGLE_ENABLED_APP);
+                Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE,
+                GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_ALL_ANGLE);
+        dumpSetting(s, p,
+                Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS,
+                GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_SELECTION_PKGS);
+        dumpSetting(s, p,
+                Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES,
+                GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_SELECTION_VALUES);
         dumpSetting(s, p,
                 Settings.Global.GPU_DEBUG_LAYER_APP,
                 GlobalSettingsProto.Gpu.DEBUG_LAYER_APP);
@@ -998,6 +1015,9 @@
         dumpSetting(s, p,
                 Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
                 GlobalSettingsProto.Notification.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS);
+        dumpSetting(s, p,
+                Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS,
+                GlobalSettingsProto.Notification.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS);
         p.end(notificationToken);
 
         dumpSetting(s, p,
@@ -1165,12 +1185,6 @@
                 GlobalSettingsProto.SmartSelection.UPDATE_METADATA_URL);
         p.end(smartSelectToken);
 
-        final long smartSuggestionsToken = p.start(GlobalSettingsProto.SMART_SUGGESTIONS);
-        dumpSetting(s, p,
-                Settings.Global.SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED,
-                GlobalSettingsProto.SmartSuggestions.SERVICE_EXPLICITLY_ENABLED);
-        p.end(smartSuggestionsToken);
-
         final long smsToken = p.start(GlobalSettingsProto.SMS);
         dumpSetting(s, p,
                 Settings.Global.SMS_OUTGOING_CHECK_INTERVAL_MS,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 00ea45c..424368d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -94,6 +94,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
@@ -147,6 +148,7 @@
     private static final String TABLE_SYSTEM = "system";
     private static final String TABLE_SECURE = "secure";
     private static final String TABLE_GLOBAL = "global";
+    private static final String TABLE_CONFIG = "config";
 
     // Old tables no longer exist.
     private static final String TABLE_FAVORITES = "favorites";
@@ -333,6 +335,7 @@
             startWatchingUserRestrictionChanges();
         });
         ServiceManager.addService("settings", new SettingsService(this));
+        ServiceManager.addService("device_config", new DeviceConfigService(this));
         return true;
     }
 
@@ -414,9 +417,8 @@
 
             case Settings.CALL_METHOD_PUT_CONFIG: {
                 String value = getSettingValue(args);
-                String tag = getSettingTag(args);
                 final boolean makeDefault = getSettingMakeDefault(args);
-                insertConfigSetting(name, value, tag, makeDefault, requestingUserId, false);
+                insertConfigSetting(name, value, null, makeDefault, requestingUserId, false);
                 break;
             }
 
@@ -444,8 +446,8 @@
 
             case Settings.CALL_METHOD_RESET_CONFIG: {
                 final int mode = getResetModeEnforcingPermission(args);
-                String tag = getSettingTag(args);
-                resetConfigSetting(requestingUserId, mode, tag);
+                String prefix = getSettingPrefix(args);
+                resetConfigSetting(requestingUserId, mode, prefix);
                 break;
             }
 
@@ -463,15 +465,8 @@
                 break;
             }
 
-            case Settings.CALL_METHOD_DELETE_SYSTEM: {
-                int rows = deleteSystemSetting(name, requestingUserId) ? 1 : 0;
-                Bundle result = new Bundle();
-                result.putInt(RESULT_ROWS_DELETED, rows);
-                return result;
-            }
-
-            case Settings.CALL_METHOD_DELETE_SECURE: {
-                int rows = deleteSecureSetting(name, requestingUserId, false) ? 1 : 0;
+            case Settings.CALL_METHOD_DELETE_CONFIG: {
+                int rows  = deleteConfigSetting(name, requestingUserId, false) ? 1 : 0;
                 Bundle result = new Bundle();
                 result.putInt(RESULT_ROWS_DELETED, rows);
                 return result;
@@ -484,10 +479,32 @@
                 return result;
             }
 
-            case Settings.CALL_METHOD_LIST_SYSTEM: {
+            case Settings.CALL_METHOD_DELETE_SECURE: {
+                int rows = deleteSecureSetting(name, requestingUserId, false) ? 1 : 0;
+                Bundle result = new Bundle();
+                result.putInt(RESULT_ROWS_DELETED, rows);
+                return result;
+            }
+
+            case Settings.CALL_METHOD_DELETE_SYSTEM: {
+                int rows = deleteSystemSetting(name, requestingUserId) ? 1 : 0;
+                Bundle result = new Bundle();
+                result.putInt(RESULT_ROWS_DELETED, rows);
+                return result;
+            }
+
+            case Settings.CALL_METHOD_LIST_CONFIG: {
+                String prefix = getSettingPrefix(args);
+                Bundle result = new Bundle();
+                result.putSerializable(
+                        Settings.NameValueTable.VALUE, (HashMap) getAllConfigFlags(prefix));
+                return result;
+            }
+
+            case Settings.CALL_METHOD_LIST_GLOBAL: {
                 Bundle result = new Bundle();
                 result.putStringArrayList(RESULT_SETTINGS_LIST,
-                        buildSettingsList(getAllSystemSettings(requestingUserId, null)));
+                        buildSettingsList(getAllGlobalSettings(null)));
                 return result;
             }
 
@@ -498,10 +515,10 @@
                 return result;
             }
 
-            case Settings.CALL_METHOD_LIST_GLOBAL: {
+            case Settings.CALL_METHOD_LIST_SYSTEM: {
                 Bundle result = new Bundle();
                 result.putStringArrayList(RESULT_SETTINGS_LIST,
-                        buildSettingsList(getAllGlobalSettings(null)));
+                        buildSettingsList(getAllSystemSettings(requestingUserId, null)));
                 return result;
             }
 
@@ -1061,36 +1078,47 @@
                 MUTATION_OPERATION_INSERT, forceNotify, 0);
     }
 
-    private void resetConfigSetting(int requestingUserId, int mode, String tag) {
+    private boolean deleteConfigSetting(String name, int requestingUserId, boolean forceNotify) {
+        if (DEBUG) {
+            Slog.v(LOG_TAG, "deleteConfigSetting(" + name + ", " + requestingUserId
+                    + ", " + forceNotify + ")");
+        }
+        return mutateConfigSetting(name, null, null, false, requestingUserId,
+                MUTATION_OPERATION_DELETE, forceNotify, 0);
+    }
+
+    private void resetConfigSetting(int requestingUserId, int mode, String prefix) {
         if (DEBUG) {
             Slog.v(LOG_TAG, "resetConfigSetting(" + requestingUserId + ", "
-                    + mode + ", " + tag + ")");
+                    + mode + ", " + prefix + ")");
         }
-        mutateConfigSetting(null, null, tag, false, requestingUserId,
+        mutateConfigSetting(null, null, prefix, false, requestingUserId,
                 MUTATION_OPERATION_RESET, false, mode);
     }
 
-    private boolean mutateConfigSetting(String name, String value, String tag,
+    private boolean mutateConfigSetting(String name, String value, String prefix,
             boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,
             int mode) {
         // TODO(b/117663715): check the new permission when it's added.
         // enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
 
-        // Resolve the userId on whose behalf the call is made.
-        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
-
         // Perform the mutation.
         synchronized (mLock) {
             switch (operation) {
                 case MUTATION_OPERATION_INSERT: {
                     return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_CONFIG,
-                            UserHandle.USER_SYSTEM, name, value, tag, makeDefault,
+                            UserHandle.USER_SYSTEM, name, value, null, makeDefault,
                             getCallingPackage(), forceNotify, null);
                 }
 
+                case MUTATION_OPERATION_DELETE: {
+                    return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_CONFIG,
+                            UserHandle.USER_SYSTEM, name, forceNotify, null);
+                }
+
                 case MUTATION_OPERATION_RESET: {
                     mSettingsRegistry.resetSettingsLocked(SETTINGS_TYPE_CONFIG,
-                            UserHandle.USER_SYSTEM, getCallingPackage(), mode, tag);
+                            UserHandle.USER_SYSTEM, getCallingPackage(), mode, null, prefix);
                 } return true;
             }
         }
@@ -1098,6 +1126,34 @@
         return false;
     }
 
+    private Map<String, String> getAllConfigFlags(@Nullable String prefix) {
+        if (DEBUG) {
+            Slog.v(LOG_TAG, "getAllConfigFlags() for " + prefix);
+        }
+
+        synchronized (mLock) {
+            // Get the settings.
+            SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
+                    SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM);
+
+            List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_CONFIG,
+                    UserHandle.USER_SYSTEM);
+
+            final int nameCount = names.size();
+            Map<String, String> flagsToValues = new HashMap<>(names.size());
+
+            for (int i = 0; i < nameCount; i++) {
+                String name = names.get(i);
+                Setting setting = settingsState.getSettingLocked(name);
+                if (prefix == null || setting.getName().startsWith(prefix)) {
+                    flagsToValues.put(setting.getName(), setting.getValue());
+                }
+            }
+
+            return flagsToValues;
+        }
+    }
+
     private Cursor getAllGlobalSettings(String[] projection) {
         if (DEBUG) {
             Slog.v(LOG_TAG, "getAllGlobalSettings()");
@@ -2085,6 +2141,13 @@
         return (args != null) ? args.getString(Settings.CALL_METHOD_TAG_KEY) : null;
     }
 
+    private static String getSettingPrefix(Bundle args) {
+        String prefix = (args != null) ? args.getString(Settings.CALL_METHOD_PREFIX_KEY) : null;
+        // Append '/' to ensure we only match properties with this exact prefix.
+        // i.e. "foo" should match "foo/property" but not "foobar/property"
+        return prefix != null ? prefix + "/" : null;
+    }
+
     private static boolean getSettingMakeDefault(Bundle args) {
         return (args != null) && args.getBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY);
     }
@@ -2644,6 +2707,11 @@
 
         public void resetSettingsLocked(int type, int userId, String packageName, int mode,
                 String tag) {
+            resetSettingsLocked(type, userId, packageName, mode, tag, null);
+        }
+
+        public void resetSettingsLocked(int type, int userId, String packageName, int mode,
+                String tag, @Nullable String prefix) {
             final int key = makeKey(type, userId);
             SettingsState settingsState = peekSettingsStateLocked(key);
             if (settingsState == null) {
@@ -2656,7 +2724,8 @@
                         boolean someSettingChanged = false;
                         Setting setting = settingsState.getSettingLocked(name);
                         if (packageName.equals(setting.getPackageName())) {
-                            if (tag != null && !tag.equals(setting.getTag())) {
+                            if ((tag != null && !tag.equals(setting.getTag()))
+                                    || (prefix != null && !setting.getName().startsWith(prefix))) {
                                 continue;
                             }
                             if (settingsState.resetSettingLocked(name)) {
@@ -2676,6 +2745,9 @@
                         Setting setting = settingsState.getSettingLocked(name);
                         if (!SettingsState.isSystemPackage(getContext(),
                                 setting.getPackageName())) {
+                            if (prefix != null && !setting.getName().startsWith(prefix)) {
+                                continue;
+                            }
                             if (settingsState.resetSettingLocked(name)) {
                                 someSettingChanged = true;
                                 notifyForSettingsChange(key, name);
@@ -2693,6 +2765,9 @@
                         Setting setting = settingsState.getSettingLocked(name);
                         if (!SettingsState.isSystemPackage(getContext(),
                                 setting.getPackageName())) {
+                            if (prefix != null && !setting.getName().startsWith(prefix)) {
+                                continue;
+                            }
                             if (setting.isDefaultFromSystem()) {
                                 if (settingsState.resetSettingLocked(name)) {
                                     someSettingChanged = true;
@@ -2713,6 +2788,9 @@
                     for (String name : settingsState.getSettingNamesLocked()) {
                         Setting setting = settingsState.getSettingLocked(name);
                         boolean someSettingChanged = false;
+                        if (prefix != null && !setting.getName().startsWith(prefix)) {
+                            continue;
+                        }
                         if (setting.isDefaultFromSystem()) {
                             if (settingsState.resetSettingLocked(name)) {
                                 someSettingChanged = true;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
index 13537c4..36360a3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
@@ -105,7 +105,7 @@
             RESET,
         }
 
-        int mUser = -1;     // unspecified
+        int mUser = UserHandle.USER_NULL;
         CommandVerb mVerb = CommandVerb.UNSPECIFIED;
         String mTable = null;
         String mKey = null;
@@ -132,15 +132,15 @@
             String arg = cmd;
             do {
                 if ("--user".equals(arg)) {
-                    if (mUser != -1) {
-                        // --user specified more than once; invalid
+                    if (mUser != UserHandle.USER_NULL) {
+                        perr.println("Invalid user: --user specified more than once");
                         break;
                     }
-                    arg = getNextArgRequired();
-                    if ("current".equals(arg) || "cur".equals(arg)) {
-                        mUser = UserHandle.USER_CURRENT;
-                    } else {
-                        mUser = Integer.parseInt(arg);
+                    mUser = UserHandle.parseUserArg(getNextArgRequired());
+
+                    if (mUser == UserHandle.USER_ALL) {
+                        perr.println("Invalid user: all");
+                        return -1;
                     }
                 } else if (mVerb == CommandVerb.UNSPECIFIED) {
                     if ("get".equalsIgnoreCase(arg)) {
@@ -254,16 +254,13 @@
                 return -1;
             }
 
-            if (mUser == UserHandle.USER_CURRENT) {
+            if (mUser == UserHandle.USER_NULL || mUser == UserHandle.USER_CURRENT) {
                 try {
                     mUser = ActivityManager.getService().getCurrentUser().id;
                 } catch (RemoteException e) {
                     throw new RuntimeException("Failed in IPC", e);
                 }
             }
-            if (mUser < 0) {
-                mUser = UserHandle.USER_SYSTEM;
-            }
             UserManager userManager = UserManager.get(mProvider.getContext());
             if (userManager.getUserInfo(mUser) == null) {
                 perr.println("Invalid user: " + mUser);
@@ -312,8 +309,8 @@
             try {
                 Bundle arg = new Bundle();
                 arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
-                Bundle result =
-                        provider.call(resolveCallingPackage(), callListCommand, null, arg);
+                Bundle result = provider.call(resolveCallingPackage(), Settings.AUTHORITY,
+                        callListCommand, null, arg);
                 lines.addAll(result.getStringArrayList(SettingsProvider.RESULT_SETTINGS_LIST));
                 Collections.sort(lines);
             } catch (RemoteException e) {
@@ -337,7 +334,8 @@
             try {
                 Bundle arg = new Bundle();
                 arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
-                Bundle b = provider.call(resolveCallingPackage(), callGetCommand, key, arg);
+                Bundle b = provider.call(resolveCallingPackage(), Settings.AUTHORITY,
+                        callGetCommand, key, arg);
                 if (b != null) {
                     result = b.getPairValue();
                 }
@@ -374,7 +372,8 @@
                 if (makeDefault) {
                     arg.putBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY, true);
                 }
-                provider.call(resolveCallingPackage(), callPutCommand, key, arg);
+                provider.call(resolveCallingPackage(), Settings.AUTHORITY,
+                        callPutCommand, key, arg);
             } catch (RemoteException e) {
                 throw new RuntimeException("Failed in IPC", e);
             }
@@ -397,8 +396,8 @@
             try {
                 Bundle arg = new Bundle();
                 arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
-                Bundle result =
-                        provider.call(resolveCallingPackage(), callDeleteCommand, key, arg);
+                Bundle result = provider.call(resolveCallingPackage(), Settings.AUTHORITY,
+                        callDeleteCommand, key, arg);
                 return result.getInt(SettingsProvider.RESULT_ROWS_DELETED);
             } catch (RemoteException e) {
                 throw new RuntimeException("Failed in IPC", e);
@@ -424,7 +423,7 @@
                 }
                 String packageName = mPackageName != null ? mPackageName : resolveCallingPackage();
                 arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
-                provider.call(packageName, callResetCommand, null, arg);
+                provider.call(packageName, Settings.AUTHORITY, callResetCommand, null, arg);
             } catch (RemoteException e) {
                 throw new RuntimeException("Failed in IPC", e);
             }
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java
new file mode 100644
index 0000000..59de6a7e
--- /dev/null
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java
@@ -0,0 +1,236 @@
+/*
+ * 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.providers.settings;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import libcore.io.Streams;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Tests for {@link DeviceConfigService}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class DeviceConfigServiceTest {
+    /**
+     * TODO(b/113100523): Move this to DeviceConfig.java when it is added, and expose it as a System
+     *     API.
+     */
+    private static final Uri CONFIG_CONTENT_URI =
+            Uri.parse("content://" + Settings.AUTHORITY + "/config");
+    private static final String sNamespace = "namespace1";
+    private static final String sKey = "key1";
+    private static final String sValue = "value1";
+
+    private ContentResolver mContentResolver;
+
+    @Before
+    public void setUp() {
+        mContentResolver = InstrumentationRegistry.getContext().getContentResolver();
+    }
+
+    @After
+    public void cleanUp() {
+        deleteFromContentProvider(mContentResolver, sNamespace, sKey);
+    }
+
+    @Test
+    public void testPut() throws Exception {
+        final String newNamespace = "namespace2";
+        final String newValue = "value2";
+
+        String result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+        assertNull(result);
+
+        try {
+            executeShellCommand("device_config put " + sNamespace + " " + sKey + " " + sValue);
+            executeShellCommand("device_config put " + newNamespace + " " + sKey + " " + newValue);
+
+            result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+            assertEquals(sValue, result);
+            result = getFromContentProvider(mContentResolver, newNamespace, sKey);
+            assertEquals(newValue, result);
+        } finally {
+            deleteFromContentProvider(mContentResolver, newNamespace, sKey);
+        }
+    }
+
+    @Test
+    public void testPut_invalidArgs() throws Exception {
+        // missing sNamespace
+        executeShellCommand("device_config put " + sKey + " " + sValue);
+        String result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+        // still null
+        assertNull(result);
+
+        // too many arguments
+        executeShellCommand(
+                "device_config put " + sNamespace + " " + sKey + " " + sValue + " extra_arg");
+        result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+        // still null
+        assertNull(result);
+    }
+
+    @Test
+    public void testDelete() throws Exception {
+        final String newNamespace = "namespace2";
+
+        putWithContentProvider(mContentResolver, sNamespace, sKey, sValue);
+        putWithContentProvider(mContentResolver, newNamespace, sKey, sValue);
+        String result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+        assertEquals(sValue, result);
+        result = getFromContentProvider(mContentResolver, newNamespace, sKey);
+        assertEquals(sValue, result);
+
+        try {
+            executeShellCommand("device_config delete " + sNamespace + " " + sKey);
+            // sKey is deleted from sNamespace
+            result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+            assertNull(result);
+            // sKey is not deleted from newNamespace
+            result = getFromContentProvider(mContentResolver, newNamespace, sKey);
+            assertEquals(sValue, result);
+        } finally {
+            deleteFromContentProvider(mContentResolver, newNamespace, sKey);
+        }
+    }
+
+    @Test
+    public void testDelete_invalidArgs() throws Exception {
+        putWithContentProvider(mContentResolver, sNamespace, sKey, sValue);
+        String result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+        assertEquals(sValue, result);
+
+        // missing sNamespace
+        executeShellCommand("device_config delete " + sKey);
+        result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+        // sValue was not deleted
+        assertEquals(sValue, result);
+
+        // too many arguments
+        executeShellCommand("device_config delete " + sNamespace + " " + sKey + " extra_arg");
+        result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+        // sValue was not deleted
+        assertEquals(sValue, result);
+    }
+
+    @Test
+    public void testReset_setUntrustedDefault() throws Exception {
+        String newValue = "value2";
+
+        // make sValue the untrusted default (set by root)
+        executeShellCommand(
+                "device_config put " + sNamespace + " " + sKey + " " + sValue + " default");
+        // make newValue the current value
+        executeShellCommand(
+                "device_config put " + sNamespace + " " + sKey + " " + newValue);
+        String result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+        assertEquals(newValue, result);
+
+        executeShellCommand("device_config reset untrusted_defaults " + sNamespace);
+        result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+        // back to the default
+        assertEquals(sValue, result);
+
+        executeShellCommand("device_config reset trusted_defaults " + sNamespace);
+        result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+        // not trusted default was set
+        assertNull(result);
+    }
+
+    @Test
+    public void testReset_setTrustedDefault() throws Exception {
+        String newValue = "value2";
+
+        // make sValue the trusted default (set by system)
+        putWithContentProvider(mContentResolver, sNamespace, sKey, sValue, true);
+        // make newValue the current value
+        executeShellCommand(
+                "device_config put " + sNamespace + " " + sKey + " " + newValue);
+        String result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+        assertEquals(newValue, result);
+
+        executeShellCommand("device_config reset untrusted_defaults " + sNamespace);
+        result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+        // back to the default
+        assertEquals(sValue, result);
+
+        executeShellCommand("device_config reset trusted_defaults " + sNamespace);
+        result = getFromContentProvider(mContentResolver, sNamespace, sKey);
+        // our trusted default is still set
+        assertEquals(sValue, result);
+    }
+
+    private static void executeShellCommand(String command) throws IOException {
+        InputStream is = new FileInputStream(InstrumentationRegistry.getInstrumentation()
+                .getUiAutomation().executeShellCommand(command).getFileDescriptor());
+        Streams.readFully(is);
+    }
+
+    private static void putWithContentProvider(ContentResolver resolver, String namespace,
+            String key, String value) {
+        putWithContentProvider(resolver, namespace, key, value, false);
+    }
+
+    private static void putWithContentProvider(ContentResolver resolver, String namespace,
+            String key, String value, boolean makeDefault) {
+        String compositeName = namespace + "/" + key;
+        Bundle args = new Bundle();
+        args.putString(Settings.NameValueTable.VALUE, value);
+        if (makeDefault) {
+            args.putBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY, true);
+        }
+        resolver.call(
+                CONFIG_CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, compositeName, args);
+    }
+
+    private static String getFromContentProvider(ContentResolver resolver, String namespace,
+            String key) {
+        String compositeName = namespace + "/" + key;
+        Bundle result = resolver.call(
+                CONFIG_CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, compositeName, null);
+        assertNotNull(result);
+        return result.getString(Settings.NameValueTable.VALUE);
+    }
+
+    private static boolean deleteFromContentProvider(ContentResolver resolver, String namespace,
+            String key) {
+        String compositeName = namespace + "/" + key;
+        Bundle result = resolver.call(
+                CONFIG_CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, compositeName, null);
+        assertNotNull(result);
+        return compositeName.equals(result.getString(Settings.NameValueTable.VALUE));
+    }
+}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 83e8369..5fe08aa 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -51,6 +51,7 @@
     <uses-permission android:name="android.permission.REAL_GET_TASKS" />
     <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
     <uses-permission android:name="android.permission.REORDER_TASKS" />
+    <uses-permission android:name="android.permission.REMOVE_TASKS" />
     <uses-permission android:name="android.permission.SET_ANIMATION_SCALE" />
     <uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
@@ -130,7 +131,7 @@
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
     <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
     <uses-permission android:name="android.permission.MANAGE_AUTO_FILL" />
-    <uses-permission android:name="android.permission.MANAGE_SMART_SUGGESTIONS" />
+    <uses-permission android:name="android.permission.MANAGE_CONTENT_CAPTURE" />
     <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
     <uses-permission android:name="android.permission.SET_TIME" />
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
index 7cb63ea..1a18f60 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
@@ -18,6 +18,8 @@
 
 import com.android.systemui.plugins.annotations.ProvidesInterface;
 
+import java.util.TimeZone;
+
 /**
  * This plugin is used to replace main clock in keyguard.
  */
@@ -55,4 +57,9 @@
      * @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake.
      */
     default void setDarkAmount(float darkAmount) {}
+
+    /**
+     * Notifies that the time zone has changed.
+     */
+    default void onTimeZoneChanged(TimeZone timeZone) {}
 }
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 555f443..9245c30 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -31,7 +31,7 @@
 
     <!-- Max Height of the sliding KeyguardSecurityContainer
          (includes 2x keyguard_security_view_top_margin) -->
-    <dimen name="keyguard_security_max_height">450dp</dimen>
+    <dimen name="keyguard_security_max_height">455dp</dimen>
 
     <!-- Margin around the various security views -->
     <dimen name="keyguard_security_view_top_margin">8dp</dimen>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 8e0bfb6..b6c9b8c 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -23,6 +23,8 @@
     <dimen name="navigation_bar_size">@*android:dimen/navigation_bar_height</dimen>
     <!-- Minimum swipe distance to catch the swipe gestures to invoke assist or switch tasks. -->
     <dimen name="navigation_bar_min_swipe_distance">48dp</dimen>
+    <!-- The distance from a side of device of the navigation bar to start an edge swipe -->
+    <dimen name="navigation_bar_edge_swipe_threshold">60dp</dimen>
 
     <!-- thickness (height) of the dead zone at the top of the navigation bar,
          reducing false presses on navbar buttons; approx 2mm -->
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index b439c6c..0ec9014 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -17,6 +17,7 @@
 import com.android.systemui.shared.plugins.PluginManager;
 
 import java.util.Objects;
+import java.util.TimeZone;
 
 /**
  * Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
@@ -162,6 +163,15 @@
     }
 
     /**
+     * Notifies that the time zone has changed.
+     */
+    public void onTimeZoneChanged(TimeZone timeZone) {
+        if (mClockPlugin != null) {
+            mClockPlugin.onTimeZoneChanged(timeZone);
+        }
+    }
+
+    /**
      * When plugin changes, set all kept parameters into newer plugin.
      */
     private void initPluginParams() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index be795d2..1e9d288 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -51,6 +51,7 @@
 import com.google.android.collect.Sets;
 
 import java.util.Locale;
+import java.util.TimeZone;
 
 public class KeyguardStatusView extends GridLayout implements
         ConfigurationController.ConfigurationListener, View.OnLayoutChangeListener {
@@ -85,6 +86,11 @@
         }
 
         @Override
+        public void onTimeZoneChanged(TimeZone timeZone) {
+            updateTimeZone(timeZone);
+        }
+
+        @Override
         public void onKeyguardVisibilityChanged(boolean showing) {
             if (showing) {
                 if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
@@ -282,6 +288,10 @@
         mClockView.refresh();
     }
 
+    private void updateTimeZone(TimeZone timeZone) {
+        mClockView.onTimeZoneChanged(timeZone);
+    }
+
     private void refreshFormat() {
         Patterns.update(mContext);
         mClockView.setFormat12Hour(Patterns.clockView12);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 904f9448..416441e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -98,6 +98,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map.Entry;
+import java.util.TimeZone;
 
 /**
  * Watches for updates that may be interesting to the keyguard, and provides
@@ -151,6 +152,7 @@
     private static final int MSG_BIOMETRIC_AUTHENTICATION_CONTINUE = 336;
     private static final int MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED = 337;
     private static final int MSG_TELEPHONY_CAPABLE = 338;
+    private static final int MSG_TIMEZONE_UPDATE = 339;
 
     /** Biometric authentication state: Not listening. */
     private static final int BIOMETRIC_STATE_STOPPED = 0;
@@ -260,6 +262,9 @@
                 case MSG_TIME_UPDATE:
                     handleTimeUpdate();
                     break;
+                case MSG_TIMEZONE_UPDATE:
+                    handleTimeZoneUpdate((String) msg.obj);
+                    break;
                 case MSG_BATTERY_UPDATE:
                     handleBatteryUpdate((BatteryStatus) msg.obj);
                     break;
@@ -964,9 +969,12 @@
             if (DEBUG) Log.d(TAG, "received broadcast " + action);
 
             if (Intent.ACTION_TIME_TICK.equals(action)
-                    || Intent.ACTION_TIME_CHANGED.equals(action)
-                    || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
+                    || Intent.ACTION_TIME_CHANGED.equals(action)) {
                 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
+            } else if (Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
+                final Message msg = mHandler.obtainMessage(
+                        MSG_TIMEZONE_UPDATE, intent.getStringExtra("time-zone"));
+                mHandler.sendMessage(msg);
             } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
                 final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
                 final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
@@ -1860,6 +1868,21 @@
     }
 
     /**
+     * Handle (@line #MSG_TIMEZONE_UPDATE}
+     */
+    private void handleTimeZoneUpdate(String timeZone) {
+        if (DEBUG) Log.d(TAG, "handleTimeZoneUpdate");
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onTimeZoneChanged(TimeZone.getTimeZone(timeZone));
+                // Also notify callbacks about time change to remain compatible.
+                cb.onTimeChanged();
+            }
+        }
+    }
+
+    /**
      * Handle {@link #MSG_BATTERY_UPDATE}
      */
     private void handleBatteryUpdate(BatteryStatus status) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index f818d05..8696bb7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -26,6 +26,8 @@
 import com.android.internal.telephony.IccCardConstants;
 import com.android.systemui.statusbar.KeyguardIndicationController;
 
+import java.util.TimeZone;
+
 /**
  * Callback for general information relevant to lock screen.
  */
@@ -49,6 +51,13 @@
     public void onTimeChanged() { }
 
     /**
+     * Called when time zone changes.
+     *
+     * @note When time zone changes, onTimeChanged will be called too.
+     */
+    public void onTimeZoneChanged(TimeZone timeZone) { }
+
+    /**
      * Called when the carrier PLMN or SPN changes.
      */
     public void onRefreshCarrierInfo() { }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 5c259d5..1e91ef3 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -32,6 +32,7 @@
 import android.view.WindowManager;
 import android.widget.FrameLayout;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.NotificationData;
@@ -72,7 +73,8 @@
     private Point mDisplaySize;
 
     // Bubbles get added to the status bar view
-    private StatusBarWindowController mStatusBarWindowController;
+    @VisibleForTesting
+    protected StatusBarWindowController mStatusBarWindowController;
 
     // Used for determining view rect for touch interaction
     private Rect mTempRect = new Rect();
@@ -302,6 +304,11 @@
         return mTempRect;
     }
 
+    @VisibleForTesting
+    public BubbleStackView getStackView() {
+        return mStackView;
+    }
+
     // TODO: factor in PIP location / maybe last place user had it
     /**
      * Gets an appropriate starting point to position the bubble stack.
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 8495fd3..86ce60d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -224,6 +224,9 @@
                         // next tap
                         mTouchState.scheduleDoubleTapTimeoutCallback();
                     }
+                    // Fall through
+                case MotionEvent.ACTION_CANCEL:
+                    mTouchState.reset();
                     break;
             }
             return true;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 451297b..cc27135 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -17,9 +17,10 @@
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_CLICK;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_LONG_PRESS;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_SECONDARY_CLICK;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CONTEXT;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_IS_FULL_QS;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_QS_POSITION;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_QS_VALUE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_STATUS_BAR_STATE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION;
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
@@ -52,6 +53,7 @@
 import com.android.systemui.qs.PagedTileLayout.TilePage;
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.QuickStatusBarHeader;
+import com.android.systemui.statusbar.StatusBarStateController;
 
 import java.util.ArrayList;
 
@@ -61,6 +63,8 @@
  * State management done on a looper provided by the host.  Tiles should update state in
  * handleUpdateState.  Callbacks affecting state should use refreshState to trigger another
  * state update pass on tile looper.
+ *
+ * @param <TState> see above
  */
 public abstract class QSTileImpl<TState extends State> implements QSTile {
     protected final String TAG = "Tile." + getClass().getSimpleName();
@@ -76,6 +80,8 @@
     protected final Handler mUiHandler = new Handler(Looper.getMainLooper());
     private final ArraySet<Object> mListeners = new ArraySet<>();
     private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
+    private final StatusBarStateController
+            mStatusBarStateController = Dependency.get(StatusBarStateController.class);
 
     private final ArrayList<Callback> mCallbacks = new ArrayList<>();
     private final Object mStaleListener = new Object();
@@ -172,17 +178,23 @@
     }
 
     public void click() {
-        mMetricsLogger.write(populate(new LogMaker(ACTION_QS_CLICK).setType(TYPE_ACTION)));
+        mMetricsLogger.write(populate(new LogMaker(ACTION_QS_CLICK).setType(TYPE_ACTION)
+                .addTaggedData(FIELD_STATUS_BAR_STATE,
+                        mStatusBarStateController.getState())));
         mHandler.sendEmptyMessage(H.CLICK);
     }
 
     public void secondaryClick() {
-        mMetricsLogger.write(populate(new LogMaker(ACTION_QS_SECONDARY_CLICK).setType(TYPE_ACTION)));
+        mMetricsLogger.write(populate(new LogMaker(ACTION_QS_SECONDARY_CLICK).setType(TYPE_ACTION)
+                .addTaggedData(FIELD_STATUS_BAR_STATE,
+                        mStatusBarStateController.getState())));
         mHandler.sendEmptyMessage(H.SECONDARY_CLICK);
     }
 
     public void longClick() {
-        mMetricsLogger.write(populate(new LogMaker(ACTION_QS_LONG_PRESS).setType(TYPE_ACTION)));
+        mMetricsLogger.write(populate(new LogMaker(ACTION_QS_LONG_PRESS).setType(TYPE_ACTION)
+                .addTaggedData(FIELD_STATUS_BAR_STATE,
+                        mStatusBarStateController.getState())));
         mHandler.sendEmptyMessage(H.LONG_CLICK);
 
         Prefs.putInt(
@@ -196,7 +208,7 @@
             logMaker.addTaggedData(FIELD_QS_VALUE, ((BooleanState) mState).value ? 1 : 0);
         }
         return logMaker.setSubtype(getMetricsCategory())
-                .addTaggedData(FIELD_CONTEXT, mIsFullQs)
+                .addTaggedData(FIELD_IS_FULL_QS, mIsFullQs)
                 .addTaggedData(FIELD_QS_POSITION, mHost.indexOf(mTileSpec));
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
index 3334f8b..a5c0a2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
@@ -67,7 +67,7 @@
     /**
      * True if the presenter is currently locked.
      */
-    default boolean isPresenterLocked() { return false; }
+    boolean isPresenterLocked();
 
     /**
      * Called when the row states are updated by {@link NotificationViewHierarchyManager}.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
index 3f8583c..d9fe982 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
@@ -815,9 +815,18 @@
     public boolean isHighPriority(StatusBarNotification statusBarNotification) {
         if (mRankingMap != null) {
             getRanking(statusBarNotification.getKey(), mTmpRanking);
-            return mTmpRanking.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT
+            if (mTmpRanking.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT
                     || statusBarNotification.getNotification().isForegroundService()
-                    || statusBarNotification.getNotification().hasMediaSession();
+                    || statusBarNotification.getNotification().hasMediaSession()) {
+                return true;
+            }
+            if (mGroupManager.isSummaryOfGroup(statusBarNotification)) {
+                for (Entry child : mGroupManager.getLogicalChildren(statusBarNotification)) {
+                    if (isHighPriority(child.notification)) {
+                        return true;
+                    }
+                }
+            }
         }
         return false;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index 50564e3..989fb21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -641,8 +641,8 @@
         NotificationInfo infoContent = (NotificationInfo) LayoutInflater.from(context).inflate(
                 R.layout.notification_info, null, false);
         int iconResId = isCurrentlySilent
-                ? R.drawable.ic_notifications_alert
-                : R.drawable.ic_notifications_silence;
+                ? R.drawable.ic_notifications_silence
+                : R.drawable.ic_notifications_alert;
         return new NotificationMenuItem(context, infoDescription, infoContent, iconResId);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
index b83ebc7..9c8b1b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
@@ -56,6 +56,11 @@
     }
 
     @Override
+    public boolean allowHitTargetToMoveOverDrag() {
+        return true;
+    }
+
+    @Override
     public boolean canPerformAction() {
         return mProxySender.getBackButtonAlpha() > 0;
     }
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 cd6e1d7..a0021ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -63,6 +63,7 @@
 import android.view.inputmethod.InputMethodManager;
 import android.widget.FrameLayout;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
 import com.android.systemui.DockedStackExistsListener;
 import com.android.systemui.Interpolators;
@@ -96,7 +97,6 @@
 
     final static boolean ALTERNATE_CAR_MODE_UI = false;
 
-    final Display mDisplay;
     View mCurrentView = null;
     View[] mRotatedViews = new View[4];
 
@@ -154,6 +154,7 @@
     private QuickScrubAction mQuickScrubAction;
     private QuickStepAction mQuickStepAction;
     private NavigationBackAction mBackAction;
+    private QuickSwitchAction mQuickSwitchAction;
 
     /**
      * Helper that is responsible for showing the right toast when a disallowed activity operation
@@ -281,8 +282,6 @@
     public NavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        mDisplay = context.getDisplay();
-
         mVertical = false;
         mLongClickableAccessibilityButton = false;
 
@@ -326,9 +325,10 @@
         mQuickScrubAction = new QuickScrubAction(this, mOverviewProxyService);
         mQuickStepAction = new QuickStepAction(this, mOverviewProxyService);
         mBackAction = new NavigationBackAction(this, mOverviewProxyService);
+        mQuickSwitchAction = new QuickSwitchAction(this, mOverviewProxyService);
         mDefaultGestureMap = new NavigationGestureAction[] {
                 mQuickStepAction, null /* swipeDownAction*/, null /* swipeLeftAction */,
-                mQuickScrubAction
+                mQuickScrubAction, null /* swipeLeftEdgeAction */, null /* swipeRightEdgeAction */
         };
 
         mPrototypeController = new NavigationPrototypeController(mHandler, mContext);
@@ -359,7 +359,9 @@
                     getNavigationActionFromType(assignedMap[0], mDefaultGestureMap[0]),
                     getNavigationActionFromType(assignedMap[1], mDefaultGestureMap[1]),
                     getNavigationActionFromType(assignedMap[2], mDefaultGestureMap[2]),
-                    getNavigationActionFromType(assignedMap[3], mDefaultGestureMap[3]));
+                    getNavigationActionFromType(assignedMap[3], mDefaultGestureMap[3]),
+                    getNavigationActionFromType(assignedMap[4], mDefaultGestureMap[4]),
+                    getNavigationActionFromType(assignedMap[5], mDefaultGestureMap[5]));
         }
     }
 
@@ -372,6 +374,8 @@
                 return mQuickScrubAction;
             case NavigationPrototypeController.ACTION_BACK:
                 return mBackAction;
+            case NavigationPrototypeController.ACTION_QUICKSWITCH:
+                return mQuickSwitchAction;
             default:
                 return defaultAction;
         }
@@ -652,8 +656,8 @@
         Log.i(TAG, "updateNavButtonIcons (b/113914868): home disabled=" + disableHome
                 + " mDisabledFlags=" + mDisabledFlags);
 
-        // Always disable recents when alternate car mode UI is active.
-        boolean disableRecent = mUseCarModeUi || !isOverviewEnabled();
+        // Always disable recents when alternate car mode UI is active and for secondary displays.
+        boolean disableRecent = isRecentsButtonDisabled();
 
         boolean disableBack = QuickStepController.shouldhideBackButton(getContext())
                 || (((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0) && !useAltBack);
@@ -689,6 +693,16 @@
         getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
     }
 
+    @VisibleForTesting
+    boolean isRecentsButtonDisabled() {
+        return mUseCarModeUi || !isOverviewEnabled()
+                || getContext().getDisplayId() != Display.DEFAULT_DISPLAY;
+    }
+
+    private Display getContextDisplay() {
+        return getContext().getDisplay();
+    }
+
     public boolean inScreenPinning() {
         return ActivityManagerWrapper.getInstance().isScreenPinningActive();
     }
@@ -890,7 +904,7 @@
     }
 
     private void updateCurrentView() {
-        final int rot = mDisplay.getRotation();
+        final int rot = getContextDisplay().getRotation();
         for (int i=0; i<4; i++) {
             mRotatedViews[i].setVisibility(View.GONE);
         }
@@ -954,7 +968,7 @@
         int navBarPos = NAV_BAR_INVALID;
         try {
             navBarPos = WindowManagerGlobal.getWindowManagerService().getNavBarPosition(
-                    mDisplay.getDisplayId());
+                    getContext().getDisplayId());
         } catch (RemoteException e) {
             Slog.e(TAG, "Failed to get nav bar position.", e);
         }
@@ -1128,7 +1142,7 @@
         pw.println("NavigationBarView {");
         final Rect r = new Rect();
         final Point size = new Point();
-        mDisplay.getRealSize(size);
+        getContextDisplay().getRealSize(size);
 
         pw.println(String.format("      this: " + StatusBar.viewInfo(this)
                         + " " + visibilityToString(getVisibility())));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
index a8d00c4..8c57fc3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
@@ -112,7 +112,7 @@
     /**
      * @return whether or not to move the button that started gesture over with user input drag
      */
-    public boolean requiresDragWithHitTarget() {
+    public boolean allowHitTargetToMoveOverDrag() {
         return false;
     }
 
@@ -139,9 +139,9 @@
      * Tell if action is enabled. Compared to {@link #canPerformAction()} this is based on settings
      * if the action is disabled for a particular gesture. For example a back action can be enabled
      * however if there is nothing to back to then {@link #canPerformAction()} should return false.
-     * In this way if the action requires {@link #requiresDragWithHitTarget()} then if enabled, the
-     * button can be dragged with a large dampening factor during the gesture but will not activate
-     * the action.
+     * In this way if the action requires {@link #allowHitTargetToMoveOverDrag()} then if enabled,
+     * the button can be dragged with a large dampening factor during the gesture but will not
+     * activate the action.
      * @return true if this action is enabled and can run
      */
     public abstract boolean isEnabled();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
index e8c0bf1..b11b6d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
@@ -24,7 +24,6 @@
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 
-import android.util.Log;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -46,6 +45,7 @@
     static final int ACTION_QUICKSTEP = 1;
     static final int ACTION_QUICKSCRUB = 2;
     static final int ACTION_BACK = 3;
+    static final int ACTION_QUICKSWITCH = 4;
 
     private OnPrototypeChangedListener mListener;
 
@@ -53,7 +53,7 @@
      * Each index corresponds to a different action set in QuickStepController
      * {@see updateSwipeLTRBackSetting}
      */
-    private int[] mActionMap = new int[4];
+    private int[] mActionMap = new int[6];
 
     private final Context mContext;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
index 2b202eb..bbfd51a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
@@ -18,8 +18,6 @@
 
 import static com.android.systemui.Interpolators.ALPHA_IN;
 import static com.android.systemui.Interpolators.ALPHA_OUT;
-import static com.android.systemui.recents.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
-import static com.android.systemui.recents.OverviewProxyService.TAG_OPS;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -31,11 +29,8 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.RadialGradient;
-import android.graphics.Rect;
 import android.graphics.Shader;
-import android.os.RemoteException;
 import android.util.FloatProperty;
-import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 
@@ -46,7 +41,7 @@
 /**
  * QuickScrub action to send to launcher to start quickscrub gesture
  */
-public class QuickScrubAction extends NavigationGestureAction {
+public class QuickScrubAction extends QuickSwitchAction {
     private static final String TAG = "QuickScrubAction";
 
     private static final float TRACK_SCALE = 0.95f;
@@ -65,7 +60,6 @@
     private final int mTrackThickness;
     private final int mTrackEndPadding;
     private final Paint mTrackPaint = new Paint();
-    private final Rect mTrackRect = new Rect();
 
     private final FloatProperty<QuickScrubAction> mTrackAlphaProperty =
             new FloatProperty<QuickScrubAction>("TrackAlpha") {
@@ -177,7 +171,7 @@
             x1 = mNavigationBarView.getPaddingStart() + mTrackEndPadding;
             x2 = x1 + width - 2 * mTrackEndPadding;
         }
-        mTrackRect.set(x1, y1, x2, y2);
+        mDragOverRect.set(x1, y1, x2, y2);
     }
 
     @Override
@@ -194,15 +188,16 @@
         mTrackPaint.setAlpha(Math.round(255f * mTrackAlpha));
 
         // Scale the track, but apply the inverse scale from the nav bar
-        final float radius = mTrackRect.height() / 2;
+        final float radius = mDragOverRect.height() / 2;
         canvas.save();
-        float translate = Utilities.clamp(mHighlightCenter, mTrackRect.left, mTrackRect.right);
+        float translate = Utilities.clamp(mHighlightCenter, mDragOverRect.left,
+                mDragOverRect.right);
         canvas.translate(translate, 0);
         canvas.scale(mTrackScale / mNavigationBarView.getScaleX(),
                 1f / mNavigationBarView.getScaleY(),
-                mTrackRect.centerX(), mTrackRect.centerY());
-        canvas.drawRoundRect(mTrackRect.left - translate, mTrackRect.top,
-                mTrackRect.right - translate, mTrackRect.bottom, radius, radius, mTrackPaint);
+                mDragOverRect.centerX(), mDragOverRect.centerY());
+        canvas.drawRoundRect(mDragOverRect.left - translate, mDragOverRect.top,
+                mDragOverRect.right - translate, mDragOverRect.bottom, radius, radius, mTrackPaint);
         canvas.restore();
     }
 
@@ -212,11 +207,6 @@
     }
 
     @Override
-    public boolean disableProxyEvents() {
-        return true;
-    }
-
-    @Override
     protected void onGestureStart(MotionEvent event) {
         updateHighlight();
         ObjectAnimator trackAnimator = ObjectAnimator.ofPropertyValuesHolder(this,
@@ -231,42 +221,12 @@
         mTrackAnimator.playTogether(trackAnimator, navBarAnimator);
         mTrackAnimator.start();
 
-        // Disable slippery for quick scrub to not cancel outside the nav bar
-        mNavigationBarView.updateSlippery();
-
-        try {
-            mProxySender.getProxy().onQuickScrubStart();
-            if (DEBUG_OVERVIEW_PROXY) {
-                Log.d(TAG_OPS, "Quick Scrub Start");
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to send start of quick scrub.", e);
-        }
-        mProxySender.notifyQuickScrubStarted();
+        startQuickGesture(event);
     }
 
     @Override
     public void onGestureMove(int x, int y) {
-        int trackSize, offset;
-        if (isNavBarVertical()) {
-            trackSize = mTrackRect.height();
-            offset = y - mTrackRect.top;
-        } else {
-            offset = x - mTrackRect.left;
-            trackSize = mTrackRect.width();
-        }
-        if (!mDragHorizontalPositive || !mDragVerticalPositive) {
-            offset -= isNavBarVertical() ? mTrackRect.height() : mTrackRect.width();
-        }
-        float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
-        try {
-            mProxySender.getProxy().onQuickScrubProgress(scrubFraction);
-            if (DEBUG_OVERVIEW_PROXY) {
-                Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to send progress of quick scrub.", e);
-        }
+        super.onGestureMove(x, y);
         mHighlightCenter = x;
         mNavigationBarView.invalidate();
     }
@@ -278,14 +238,7 @@
 
     private void endQuickScrub(boolean animate) {
         animateEnd();
-        try {
-            mProxySender.getProxy().onQuickScrubEnd();
-            if (DEBUG_OVERVIEW_PROXY) {
-                Log.d(TAG_OPS, "Quick Scrub End");
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to send end of quick scrub.", e);
-        }
+        endQuickGesture(animate);
         if (!animate) {
             if (mTrackAnimator != null) {
                 mTrackAnimator.end();
@@ -295,7 +248,7 @@
     }
 
     private void updateHighlight() {
-        if (mTrackRect.isEmpty()) {
+        if (mDragOverRect.isEmpty()) {
             return;
         }
         int colorBase, colorGrad;
@@ -306,8 +259,8 @@
             colorBase = getContext().getColor(R.color.quick_step_track_background_background_light);
             colorGrad = getContext().getColor(R.color.quick_step_track_background_foreground_light);
         }
-        final RadialGradient mHighlight = new RadialGradient(0, mTrackRect.height() / 2,
-                mTrackRect.width() * GRADIENT_WIDTH, colorGrad, colorBase,
+        final RadialGradient mHighlight = new RadialGradient(0, mDragOverRect.height() / 2,
+                mDragOverRect.width() * GRADIENT_WIDTH, colorGrad, colorBase,
                 Shader.TileMode.CLAMP);
         mTrackPaint.setShader(mHighlight);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 4983618..9eb5737a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -76,7 +76,9 @@
     private static final int ACTION_SWIPE_DOWN_INDEX = 1;
     private static final int ACTION_SWIPE_LEFT_INDEX = 2;
     private static final int ACTION_SWIPE_RIGHT_INDEX = 3;
-    private static final int MAX_GESTURES = 4;
+    private static final int ACTION_SWIPE_LEFT_FROM_EDGE_INDEX = 4;
+    private static final int ACTION_SWIPE_RIGHT_FROM_EDGE_INDEX = 5;
+    private static final int MAX_GESTURES = 6;
 
     private NavigationBarView mNavigationBarView;
 
@@ -97,6 +99,7 @@
     private float mMaxDragLimit;
     private float mMinDragLimit;
     private float mDragDampeningFactor;
+    private float mEdgeSwipeThreshold;
 
     private NavigationGestureAction mCurrentAction;
     private NavigationGestureAction[] mGestureActions = new NavigationGestureAction[MAX_GESTURES];
@@ -128,15 +131,21 @@
      * @param swipeDownAction action after swiping down
      * @param swipeLeftAction action after swiping left
      * @param swipeRightAction action after swiping right
+     * @param swipeLeftFromEdgeAction action swiping left starting from the right side
+     * @param swipeRightFromEdgeAction action swiping right starting from the left side
      */
     public void setGestureActions(@Nullable NavigationGestureAction swipeUpAction,
             @Nullable NavigationGestureAction swipeDownAction,
             @Nullable NavigationGestureAction swipeLeftAction,
-            @Nullable NavigationGestureAction swipeRightAction) {
+            @Nullable NavigationGestureAction swipeRightAction,
+            @Nullable NavigationGestureAction swipeLeftFromEdgeAction,
+            @Nullable NavigationGestureAction swipeRightFromEdgeAction) {
         mGestureActions[ACTION_SWIPE_UP_INDEX] = swipeUpAction;
         mGestureActions[ACTION_SWIPE_DOWN_INDEX] = swipeDownAction;
         mGestureActions[ACTION_SWIPE_LEFT_INDEX] = swipeLeftAction;
         mGestureActions[ACTION_SWIPE_RIGHT_INDEX] = swipeRightAction;
+        mGestureActions[ACTION_SWIPE_LEFT_FROM_EDGE_INDEX] = swipeLeftFromEdgeAction;
+        mGestureActions[ACTION_SWIPE_RIGHT_FROM_EDGE_INDEX] = swipeRightFromEdgeAction;
 
         // Set the current state to all actions
         for (NavigationGestureAction action: mGestureActions) {
@@ -233,6 +242,8 @@
                 mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
                 mAllowGestureDetection = true;
                 mNotificationsVisibleOnDown = !mNavigationBarView.isNotificationsFullyCollapsed();
+                mEdgeSwipeThreshold = mContext.getResources()
+                        .getDimensionPixelSize(R.dimen.navigation_bar_edge_swipe_threshold);
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
@@ -284,13 +295,17 @@
                         }
                     } else if (exceededSwipeHorizontalTouchSlop) {
                         if (mDragHPositive ? (posH < touchDownH) : (posH > touchDownH)) {
-                            // Swiping left (ltr) gesture
-                            tryToStartGesture(mGestureActions[ACTION_SWIPE_LEFT_INDEX],
-                                    true /* alignedWithNavBar */, event);
+                            // Swiping left (rtl) gesture
+                            int index = isEdgeSwipeAlongNavBar(touchDownH, !mDragHPositive)
+                                    ? ACTION_SWIPE_LEFT_FROM_EDGE_INDEX : ACTION_SWIPE_LEFT_INDEX;
+                            tryToStartGesture(mGestureActions[index], true /* alignedWithNavBar */,
+                                    event);
                         } else {
                             // Swiping right (ltr) gesture
-                            tryToStartGesture(mGestureActions[ACTION_SWIPE_RIGHT_INDEX],
-                                    true /* alignedWithNavBar */, event);
+                            int index = isEdgeSwipeAlongNavBar(touchDownH, mDragHPositive)
+                                    ? ACTION_SWIPE_RIGHT_FROM_EDGE_INDEX : ACTION_SWIPE_RIGHT_INDEX;
+                            tryToStartGesture(mGestureActions[index], true /* alignedWithNavBar */,
+                                    event);
                         }
                     }
                 }
@@ -333,6 +348,17 @@
         return mCurrentAction != null || deadZoneConsumed;
     }
 
+    private boolean isEdgeSwipeAlongNavBar(int touchDown, boolean dragPositiveDirection) {
+        // Detect edge swipe from side of 0 -> threshold
+        if (dragPositiveDirection) {
+            return touchDown < mEdgeSwipeThreshold;
+        }
+        // Detect edge swipe from side of size -> (size - threshold)
+        final int largeSide = isNavBarVertical()
+                ? mNavigationBarView.getHeight() : mNavigationBarView.getWidth();
+        return touchDown > largeSide - mEdgeSwipeThreshold;
+    }
+
     private void handleDragHitTarget(int position, int touchDown) {
         // Drag the hit target if gesture action requires it
         if (mHitTarget != null && (mGestureVerticalDragsButton || mGestureHorizontalDragsButton)) {
@@ -480,7 +506,7 @@
                 event.transform(mTransformLocalMatrix);
 
                 // Calculate the bounding limits of drag to avoid dragging off nav bar's window
-                if (action.requiresDragWithHitTarget() && mHitTarget != null) {
+                if (action.allowHitTargetToMoveOverDrag() && mHitTarget != null) {
                     final int[] buttonCenter = new int[2];
                     View button = mHitTarget.getCurrentView();
                     button.getLocationInWindow(buttonCenter);
@@ -505,7 +531,7 @@
 
             // Handle direction of the hit target drag from the axis that started the gesture
             // Also calculate the dampening factor, weaker dampening if there is an active action
-            if (action.requiresDragWithHitTarget()) {
+            if (action.allowHitTargetToMoveOverDrag()) {
                 if (alignedWithNavBar) {
                     mGestureHorizontalDragsButton = true;
                     mGestureVerticalDragsButton = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSwitchAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSwitchAction.java
new file mode 100644
index 0000000..40f2392
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSwitchAction.java
@@ -0,0 +1,139 @@
+/*
+ * 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.systemui.statusbar.phone;
+
+import static com.android.systemui.recents.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
+import static com.android.systemui.recents.OverviewProxyService.TAG_OPS;
+
+import android.annotation.NonNull;
+import android.graphics.Rect;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.recents.utilities.Utilities;
+
+/**
+ * QuickSwitch action to send to launcher
+ */
+public class QuickSwitchAction extends NavigationGestureAction {
+    private static final String TAG = "QuickSwitchAction";
+    private static final String QUICKSWITCH_ENABLED_SETTING = "QUICK_SWITCH";
+
+    protected final Rect mDragOverRect = new Rect();
+
+    public QuickSwitchAction(@NonNull NavigationBarView navigationBar,
+            @NonNull OverviewProxyService service) {
+        super(navigationBar, service);
+    }
+
+    @Override
+    public void setBarState(boolean changed, int navBarPos, boolean dragHorPositive,
+            boolean dragVerPositive) {
+        super.setBarState(changed, navBarPos, dragHorPositive, dragVerPositive);
+        if (changed && isActive()) {
+            // End quickscrub if the state changes mid-transition
+            endQuickGesture(false /* animate */);
+        }
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return mNavigationBarView.isQuickScrubEnabled();
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        mDragOverRect.set(top, left, right, bottom);
+    }
+
+    @Override
+    public boolean disableProxyEvents() {
+        return true;
+    }
+
+    @Override
+    protected void onGestureStart(MotionEvent event) {
+        // Temporarily enable launcher to allow quick switch instead of quick scrub
+        Settings.Global.putInt(mNavigationBarView.getContext().getContentResolver(),
+                QUICKSWITCH_ENABLED_SETTING, 1 /* enabled */);
+
+        startQuickGesture(event);
+    }
+
+    @Override
+    public void onGestureMove(int x, int y) {
+        int dragLength, offset;
+        if (isNavBarVertical()) {
+            dragLength = mDragOverRect.height();
+            offset = y - mDragOverRect.top;
+        } else {
+            offset = x - mDragOverRect.left;
+            dragLength = mDragOverRect.width();
+        }
+        if (!mDragHorizontalPositive || !mDragVerticalPositive) {
+            offset -= dragLength;
+        }
+        float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / dragLength, 0, 1);
+        try {
+            mProxySender.getProxy().onQuickScrubProgress(scrubFraction);
+            if (DEBUG_OVERVIEW_PROXY) {
+                Log.d(TAG_OPS, "Quick Switch Progress:" + scrubFraction);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to send progress of quick switch.", e);
+        }
+    }
+
+    @Override
+    protected void onGestureEnd() {
+        endQuickGesture(true /* animate */);
+
+        // Disable launcher to use quick switch instead of quick scrub
+        Settings.Global.putInt(mNavigationBarView.getContext().getContentResolver(),
+                QUICKSWITCH_ENABLED_SETTING, 0 /* disabled */);
+    }
+
+    protected void startQuickGesture(MotionEvent event) {
+        // Disable slippery for quick scrub to not cancel outside the nav bar
+        mNavigationBarView.updateSlippery();
+
+        try {
+            mProxySender.getProxy().onQuickScrubStart();
+            if (DEBUG_OVERVIEW_PROXY) {
+                Log.d(TAG_OPS, "Quick Scrub Start");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to send start of quick scrub.", e);
+        }
+        mProxySender.notifyQuickScrubStarted();
+    }
+
+    protected void endQuickGesture(boolean animate) {
+        try {
+            mProxySender.getProxy().onQuickScrubEnd();
+            if (DEBUG_OVERVIEW_PROXY) {
+                Log.d(TAG_OPS, "Quick Scrub End");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to send end of quick scrub.", e);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index bf53b77..b351f1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1023,7 +1023,7 @@
 
         mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel,
                 mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
-                mScrimController, mActivityLaunchAnimator);
+                mScrimController, mActivityLaunchAnimator, mStatusBarKeyguardViewManager);
 
         mAppOpsController.addCallback(APP_OPS, this);
         mNotificationListener.setUpWithPresenter(mPresenter);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 3550bd6..d99af1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -97,6 +97,7 @@
     private final AccessibilityManager mAccessibilityManager;
     private final KeyguardManager mKeyguardManager;
     private final ActivityLaunchAnimator mActivityLaunchAnimator;
+    private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     private final int mMaxAllowedKeyguardNotifications;
     private final IStatusBarService mBarService;
     private boolean mReinflateNotificationsOnUserSwitched;
@@ -113,13 +114,15 @@
             ViewGroup stackScroller,
             DozeScrimController dozeScrimController,
             ScrimController scrimController,
-            ActivityLaunchAnimator activityLaunchAnimator) {
+            ActivityLaunchAnimator activityLaunchAnimator,
+            StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
         mContext = context;
         mNotificationPanel = panel;
         mHeadsUpManager = headsUp;
         mCommandQueue = getComponent(context, CommandQueue.class);
         mAboveShelfObserver = new AboveShelfObserver(stackScroller);
         mActivityLaunchAnimator = activityLaunchAnimator;
+        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
         mAboveShelfObserver.setListener(statusBarWindow.findViewById(
                 R.id.notification_container_parent));
         mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
@@ -367,6 +370,12 @@
         return mVrMode;
     }
 
+    @Override
+    public boolean isPresenterLocked() {
+        return mStatusBarKeyguardViewManager.isShowing()
+                && mStatusBarKeyguardViewManager.isSecure();
+    }
+
     private void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {
         mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
         mActivityStarter.dismissKeyguardThenExecute(dismissAction, null,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 986a86d..cb6e300 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -84,7 +84,7 @@
     }
 
     @VisibleForTesting
-    StatusBarWindowController(Context context, WindowManager windowManager,
+    public StatusBarWindowController(Context context, WindowManager windowManager,
             IActivityManager activityManager, DozeParameters dozeParameters) {
         mContext = context;
         mWindowManager = windowManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestableContext.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestableContext.java
index e811270..f792d7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestableContext.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestableContext.java
@@ -18,6 +18,7 @@
 import android.testing.LeakCheck;
 import android.testing.TestableContext;
 import android.util.ArrayMap;
+import android.view.Display;
 
 public class SysuiTestableContext extends TestableContext implements SysUiServiceProvider {
 
@@ -47,4 +48,15 @@
         if (mComponents == null) mComponents = new ArrayMap<>();
         mComponents.put(interfaceType, component);
     }
+
+    @Override
+    public Context createDisplayContext(Display display) {
+        if (display == null) {
+            throw new IllegalArgumentException("display must not be null");
+        }
+
+        SysuiTestableContext context =
+                new SysuiTestableContext(getBaseContext().createDisplayContext(display));
+        return context;
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
new file mode 100644
index 0000000..16ef63f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.systemui.bubbles;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.app.IActivityManager;
+import android.content.Context;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class BubbleControllerTest extends SysuiTestCase {
+
+    @Mock
+    private WindowManager mWindowManager;
+    @Mock
+    private IActivityManager mActivityManager;
+    @Mock
+    private DozeParameters mDozeParameters;
+    @Mock
+    private FrameLayout mStatusBarView;
+
+    private TestableBubbleController mBubbleController;
+    private StatusBarWindowController mStatusBarWindowController;
+
+    private NotificationTestHelper mNotificationTestHelper;
+    private ExpandableNotificationRow mRow;
+    private ExpandableNotificationRow mRow2;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        // Bubbles get added to status bar window view
+        mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
+                mActivityManager, mDozeParameters);
+        mStatusBarWindowController.add(mStatusBarView, 120 /* height */);
+
+        // Need notifications for bubbles
+        mNotificationTestHelper = new NotificationTestHelper(mContext);
+        mRow = mNotificationTestHelper.createBubble();
+        mRow2 = mNotificationTestHelper.createBubble();
+
+        mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController);
+    }
+
+    @Test
+    public void testIsBubble() {
+        assertTrue(mRow.getEntry().isBubble());
+    }
+
+    @Test
+    public void testAddBubble() {
+        mBubbleController.addBubble(mRow.getEntry());
+        assertTrue(mBubbleController.hasBubbles());
+    }
+
+    @Test
+    public void testHasBubbles() {
+        assertFalse(mBubbleController.hasBubbles());
+        mBubbleController.addBubble(mRow.getEntry());
+        assertTrue(mBubbleController.hasBubbles());
+    }
+
+    @Test
+    public void testRemoveBubble() {
+        mBubbleController.addBubble(mRow.getEntry());
+        assertTrue(mBubbleController.hasBubbles());
+
+        mBubbleController.removeBubble(mRow.getEntry().key);
+        assertFalse(mStatusBarWindowController.getBubblesShowing());
+    }
+
+    @Test
+    public void testDismissStack() {
+        mBubbleController.addBubble(mRow.getEntry());
+        mBubbleController.addBubble(mRow2.getEntry());
+        assertTrue(mBubbleController.hasBubbles());
+
+        mBubbleController.dismissStack();
+        assertFalse(mStatusBarWindowController.getBubblesShowing());
+    }
+
+    @Test
+    public void testIsStackExpanded() {
+        assertFalse(mBubbleController.isStackExpanded());
+        mBubbleController.addBubble(mRow.getEntry());
+
+        BubbleStackView stackView = mBubbleController.getStackView();
+        stackView.animateExpansion(true /* expanded */);
+        assertTrue(mBubbleController.isStackExpanded());
+
+        stackView.animateExpansion(false /* expanded */);
+        assertFalse(mBubbleController.isStackExpanded());
+    }
+
+    @Test
+    public void testCollapseStack() {
+        mBubbleController.addBubble(mRow.getEntry());
+        mBubbleController.addBubble(mRow2.getEntry());
+
+        BubbleStackView stackView = mBubbleController.getStackView();
+        stackView.animateExpansion(true /* expanded */);
+        assertTrue(mBubbleController.isStackExpanded());
+
+        mBubbleController.collapseStack();
+        assertFalse(mBubbleController.isStackExpanded());
+    }
+
+    static class TestableBubbleController extends BubbleController {
+
+        TestableBubbleController(Context context,
+                StatusBarWindowController statusBarWindowController) {
+            super(context);
+            mStatusBarWindowController = statusBarWindowController;
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index 6764634..e5464e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -19,8 +19,10 @@
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_SECONDARY_CLICK;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_QS_POSITION;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_QS_VALUE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_STATUS_BAR_STATE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION;
 
+import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
@@ -37,7 +39,6 @@
 import android.content.Intent;
 import android.metrics.LogMaker;
 import android.support.test.filters.SmallTest;
-import android.support.test.InstrumentationRegistry;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -48,12 +49,17 @@
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
 
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.ArgumentMatcher;
+import org.mockito.Captor;
+import org.mockito.MockitoAnnotations;
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
@@ -65,13 +71,20 @@
     private TileImpl mTile;
     private QSTileHost mHost;
     private MetricsLogger mMetricsLogger;
+    private StatusBarStateController mStatusBarStateController;
+
+    @Captor
+    private ArgumentCaptor<LogMaker> mLogCaptor;
 
     @Before
     public void setup() throws Exception {
+        MockitoAnnotations.initMocks(this);
         String spec = "spec";
         mTestableLooper = TestableLooper.get(this);
         mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
         mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
+        mStatusBarStateController =
+            mDependency.injectMockDependency(StatusBarStateController.class);
         mHost = mock(QSTileHost.class);
         when(mHost.indexOf(spec)).thenReturn(POSITION);
         when(mHost.getContext()).thenReturn(mContext.getBaseContext());
@@ -88,19 +101,57 @@
     }
 
     @Test
+    public void testClick_Metrics_Status_Bar_Status() {
+        when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
+        mTile.click();
+        verify(mMetricsLogger).write(mLogCaptor.capture());
+        assertEquals(StatusBarState.SHADE, mLogCaptor.getValue()
+                .getTaggedData(FIELD_STATUS_BAR_STATE));
+    }
+
+    @Test
     public void testSecondaryClick_Metrics() {
         mTile.secondaryClick();
         verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_SECONDARY_CLICK)));
     }
 
     @Test
+    public void testSecondaryClick_Metrics_Status_Bar_Status() {
+        when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
+        mTile.secondaryClick();
+        verify(mMetricsLogger).write(mLogCaptor.capture());
+        assertEquals(StatusBarState.KEYGUARD, mLogCaptor.getValue()
+                .getTaggedData(FIELD_STATUS_BAR_STATE));
+    }
+
+    @Test
     public void testLongClick_Metrics() {
         mTile.longClick();
         verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_LONG_PRESS)));
     }
 
     @Test
-    public void testPopulate() {
+    public void testLongClick_Metrics_Status_Bar_Status() {
+        when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
+        mTile.click();
+        verify(mMetricsLogger).write(mLogCaptor.capture());
+        assertEquals(StatusBarState.SHADE_LOCKED, mLogCaptor.getValue()
+                .getTaggedData(FIELD_STATUS_BAR_STATE));
+    }
+
+    @Test
+    public void testPopulateWithLockedScreen() {
+        LogMaker maker = mock(LogMaker.class);
+        when(maker.setSubtype(anyInt())).thenReturn(maker);
+        when(maker.addTaggedData(anyInt(), any())).thenReturn(maker);
+        mTile.getState().value = true;
+        mTile.populate(maker);
+        verify(maker).addTaggedData(eq(FIELD_QS_VALUE), eq(1));
+        verify(maker).addTaggedData(eq(FIELD_QS_POSITION), eq(POSITION));
+    }
+
+    @Test
+    public void testPopulateWithUnlockedScreen() {
         LogMaker maker = mock(LogMaker.class);
         when(maker.setSubtype(anyInt())).thenReturn(maker);
         when(maker.addTaggedData(anyInt(), any())).thenReturn(maker);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index 9bed59b..fb5e875 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -33,9 +33,9 @@
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
 import com.android.systemui.statusbar.notification.row.NotificationInflaterTest;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -86,7 +86,8 @@
      * @throws Exception
      */
     public ExpandableNotificationRow createRow(String pkg, int uid) throws Exception {
-        return createRow(pkg, uid, false /* isGroupSummary */, null /* groupKey */);
+        return createRow(pkg, uid, false /* isGroupSummary */, null /* groupKey */,
+                false /* isBubble */);
     }
 
     /**
@@ -97,7 +98,8 @@
      * @throws Exception
      */
     public ExpandableNotificationRow createRow(Notification notification) throws Exception {
-        return generateRow(notification, PKG, UID, 0 /* extraInflationFlags */);
+        return generateRow(notification, PKG, UID, 0 /* extraInflationFlags */,
+                false /* isBubble */);
     }
 
     /**
@@ -110,7 +112,8 @@
      */
     public ExpandableNotificationRow createRow(@InflationFlag int extraInflationFlags)
             throws Exception {
-        return generateRow(createNotification(), PKG, UID, extraInflationFlags);
+        return generateRow(createNotification(), PKG, UID, extraInflationFlags,
+                false /* isBubble */);
     }
 
     /**
@@ -131,12 +134,20 @@
         return createGroup(2);
     }
 
+    /**
+     * Retursn an {@link ExpandableNotificationRow} that should be a bubble.
+     */
+    public ExpandableNotificationRow createBubble() throws Exception {
+        return createRow(PKG, UID, false /* isGroupSummary */, null /* groupKey */,
+                true /* isBubble */);
+    }
+
     private ExpandableNotificationRow createGroupSummary(String groupkey) throws Exception {
-        return createRow(PKG, UID, true /* isGroupSummary */, groupkey);
+        return createRow(PKG, UID, true /* isGroupSummary */, groupkey, false);
     }
 
     private ExpandableNotificationRow createGroupChild(String groupkey) throws Exception {
-        return createRow(PKG, UID, false /* isGroupSummary */, groupkey);
+        return createRow(PKG, UID, false /* isGroupSummary */, groupkey, false);
     }
 
     /**
@@ -146,6 +157,7 @@
      * @param uid uid used for creating a {@link StatusBarNotification}
      * @param isGroupSummary whether the notification row is a group summary
      * @param groupKey the group key for the notification group used across notifications
+     * @param isBubble
      * @return a row with that's either a standalone notification or a group notification if the
      *         groupKey is non-null
      * @throws Exception
@@ -154,10 +166,10 @@
             String pkg,
             int uid,
             boolean isGroupSummary,
-            @Nullable String groupKey)
+            @Nullable String groupKey, boolean isBubble)
             throws Exception {
         Notification notif = createNotification(isGroupSummary, groupKey);
-        return generateRow(notif, pkg, uid, 0 /* inflationFlags */);
+        return generateRow(notif, pkg, uid, 0 /* inflationFlags */, isBubble);
     }
 
     /**
@@ -202,7 +214,7 @@
             Notification notification,
             String pkg,
             int uid,
-            @InflationFlag int extraInflationFlags)
+            @InflationFlag int extraInflationFlags, boolean isBubble)
             throws Exception {
         LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
                 mContext.LAYOUT_INFLATER_SERVICE);
@@ -232,6 +244,7 @@
         entry.channel = new NotificationChannel(
                 notification.getChannelId(), notification.getChannelId(), IMPORTANCE_DEFAULT);
         entry.channel.setBlockableSystem(true);
+        entry.setIsBubble(isBubble);
         row.setEntry(entry);
         row.getNotificationInflater().addInflationFlags(extraInflationFlags);
         NotificationInflaterTest.runThenWaitForInflation(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java
new file mode 100644
index 0000000..73f3b43
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.systemui.statusbar.phone;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import android.graphics.PixelFormat;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.VirtualDisplay;
+import android.media.ImageReader;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.SysuiTestableContext;
+import com.android.systemui.statusbar.CommandQueue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** atest NavigationBarButtonTest */
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class NavigationBarButtonTest extends SysuiTestCase {
+
+    private ImageReader mReader;
+    private NavigationBarView mNavBar;
+    private VirtualDisplay mVirtualDisplay;
+
+    @Before
+    public void setup() {
+        final Display display = createVirtualDisplay();
+        final SysuiTestableContext context =
+                (SysuiTestableContext) mContext.createDisplayContext(display);
+        context.putComponent(CommandQueue.class, mock(CommandQueue.class));
+
+        mNavBar = new NavigationBarView(context, null);
+    }
+
+    private Display createVirtualDisplay() {
+        final String displayName = "NavVirtualDisplay";
+        final DisplayInfo displayInfo = new DisplayInfo();
+        mContext.getDisplay().getDisplayInfo(displayInfo);
+
+        final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+
+        mReader = ImageReader.newInstance(displayInfo.logicalWidth,
+                displayInfo.logicalHeight, PixelFormat.RGBA_8888, 2);
+
+        assertNotNull("ImageReader must not be null", mReader);
+
+        mVirtualDisplay = displayManager.createVirtualDisplay(displayName, displayInfo.logicalWidth,
+                displayInfo.logicalHeight, displayInfo.logicalDensityDpi, mReader.getSurface(),
+                0 /*flags*/);
+
+        assertNotNull("virtual display must not be null", mVirtualDisplay);
+
+        return mVirtualDisplay.getDisplay();
+    }
+
+    @After
+    public void tearDown() {
+        releaseDisplay();
+    }
+
+    private void releaseDisplay() {
+        mVirtualDisplay.release();
+        mReader.close();
+    }
+
+    @Test
+    public void testRecentsButtonDisabledOnSecondaryDisplay() {
+        assertTrue("The recents button must be disabled",
+                mNavBar.isRecentsButtonDisabled());
+    }
+}
+
+
+
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java
index cdaa242..abb8c79 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java
@@ -61,6 +61,10 @@
 @RunWithLooper
 @SmallTest
 public class QuickStepControllerTest extends SysuiTestCase {
+    private static final int NAVBAR_WIDTH = 1000;
+    private static final int NAVBAR_HEIGHT = 300;
+    private static final int EDGE_THRESHOLD = 100;
+
     private QuickStepController mController;
     private NavigationBarView mNavigationBarView;
     private StatusBar mStatusBar;
@@ -73,6 +77,8 @@
         MockitoAnnotations.initMocks(this);
         final ButtonDispatcher backButton = mock(ButtonDispatcher.class);
         mResources = mock(Resources.class);
+        doReturn(EDGE_THRESHOLD).when(mResources)
+                .getDimensionPixelSize(R.dimen.navigation_bar_edge_swipe_threshold);
 
         mProxyService = mock(OverviewProxyService.class);
         mProxy = mock(IOverviewProxy.Stub.class);
@@ -109,7 +115,8 @@
     public void testNoGesturesWhenSwipeUpDisabled() throws Exception {
         doReturn(false).when(mProxyService).shouldShowSwipeUpUI();
         mController.setGestureActions(mockAction(true), null /* swipeDownAction */,
-                null /* swipeLeftAction */, null /* swipeRightAction */);
+                null /* swipeLeftAction */, null /* swipeRightAction */,  null /* leftEdgeSwipe */,
+                null /* rightEdgeSwipe */);
 
         MotionEvent ev = event(MotionEvent.ACTION_DOWN, 1, 1);
         assertFalse(mController.onInterceptTouchEvent(ev));
@@ -124,7 +131,8 @@
         // Add enabled gesture action
         NavigationGestureAction action = mockAction(true);
         mController.setGestureActions(action, null /* swipeDownAction */,
-                null /* swipeLeftAction */, null /* swipeRightAction */);
+                null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+                null /* rightEdgeSwipe */);
 
         assertFalse(mController.onInterceptTouchEvent(ev));
         verify(mNavigationBarView, times(1)).requestUnbufferedDispatch(ev);
@@ -140,7 +148,8 @@
 
         // Add enabled gesture action
         mController.setGestureActions(mockAction(true), null /* swipeDownAction */,
-                null /* swipeLeftAction */, null /* swipeRightAction */);
+                null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+                null /* rightEdgeSwipe */);
 
         // Set the gesture on deadzone
         doReturn(null).when(mProxyService).getProxy();
@@ -165,7 +174,8 @@
     @Test
     public void testOnTouchIgnoredDownEventAfterOnIntercept() {
         mController.setGestureActions(mockAction(true), null /* swipeDownAction */,
-                null /* swipeLeftAction */, null /* swipeRightAction */);
+                null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+                null /* rightEdgeSwipe */);
 
         MotionEvent ev = event(MotionEvent.ACTION_DOWN, 1, 1);
         assertFalse(touch(ev));
@@ -178,29 +188,45 @@
 
     @Test
     public void testGesturesCallCorrectAction() throws Exception {
+        doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getWidth();
+        doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getHeight();
+
         NavigationGestureAction swipeUp = mockAction(true);
         NavigationGestureAction swipeDown = mockAction(true);
         NavigationGestureAction swipeLeft = mockAction(true);
         NavigationGestureAction swipeRight = mockAction(true);
-        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+        NavigationGestureAction swipeLeftFromEdge = mockAction(true);
+        NavigationGestureAction swipeRightFromEdge = mockAction(true);
+        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
+                swipeRightFromEdge);
 
         // Swipe Up
         assertGestureTriggersAction(swipeUp, 1, 100, 5, 1);
         // Swipe Down
         assertGestureTriggersAction(swipeDown, 1, 1, 5, 100);
         // Swipe Left
-        assertGestureTriggersAction(swipeLeft, 100, 1, 5, 1);
+        assertGestureTriggersAction(swipeLeft, NAVBAR_WIDTH / 2, 1, 5, 1);
         // Swipe Right
-        assertGestureTriggersAction(swipeRight, 1, 1, 100, 5);
+        assertGestureTriggersAction(swipeRight, NAVBAR_WIDTH / 2, 1, NAVBAR_WIDTH, 5);
+        // Swipe Left from Edge
+        assertGestureTriggersAction(swipeLeftFromEdge, NAVBAR_WIDTH, 1, 5, 1);
+        // Swipe Right from Edge
+        assertGestureTriggersAction(swipeRightFromEdge, 0, 1, NAVBAR_WIDTH, 5);
     }
 
     @Test
     public void testGesturesCallCorrectActionLandscape() throws Exception {
+        doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getWidth();
+        doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getHeight();
+
         NavigationGestureAction swipeUp = mockAction(true);
         NavigationGestureAction swipeDown = mockAction(true);
         NavigationGestureAction swipeLeft = mockAction(true);
         NavigationGestureAction swipeRight = mockAction(true);
-        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+        NavigationGestureAction swipeLeftFromEdge = mockAction(true);
+        NavigationGestureAction swipeRightFromEdge = mockAction(true);
+        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
+                swipeRightFromEdge);
 
         // In landscape
         mController.setBarState(false /* isRTL */, NAV_BAR_RIGHT);
@@ -208,34 +234,50 @@
         // Swipe Up
         assertGestureTriggersAction(swipeRight, 1, 100, 5, 1);
         // Swipe Down
-        assertGestureTriggersAction(swipeLeft, 1, 1, 5, 100);
+        assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, NAVBAR_WIDTH);
         // Swipe Left
         assertGestureTriggersAction(swipeUp, 100, 1, 5, 1);
         // Swipe Right
         assertGestureTriggersAction(swipeDown, 1, 1, 100, 5);
+        // Swipe Up from Edge
+        assertGestureTriggersAction(swipeRightFromEdge, 1, NAVBAR_WIDTH, 5, 0);
+        // Swipe Down from Edge
+        assertGestureTriggersAction(swipeLeftFromEdge, 0, 1, 0, NAVBAR_WIDTH);
     }
 
     @Test
     public void testGesturesCallCorrectActionSeascape() throws Exception {
+        doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getWidth();
+        doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getHeight();
+
         mController.setBarState(false /* isRTL */, NAV_BAR_LEFT);
         NavigationGestureAction swipeUp = mockAction(true);
         NavigationGestureAction swipeDown = mockAction(true);
         NavigationGestureAction swipeLeft = mockAction(true);
         NavigationGestureAction swipeRight = mockAction(true);
-        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+        NavigationGestureAction swipeLeftFromEdge = mockAction(true);
+        NavigationGestureAction swipeRightFromEdge = mockAction(true);
+        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
+                swipeRightFromEdge);
 
         // Swipe Up
-        assertGestureTriggersAction(swipeLeft, 1, 100, 5, 1);
+        assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, 1);
         // Swipe Down
-        assertGestureTriggersAction(swipeRight, 1, 1, 5, 100);
+        assertGestureTriggersAction(swipeRight, 1, NAVBAR_WIDTH / 2, 5, NAVBAR_WIDTH);
         // Swipe Left
         assertGestureTriggersAction(swipeDown, 100, 1, 5, 1);
         // Swipe Right
         assertGestureTriggersAction(swipeUp, 1, 1, 100, 5);
+        // Swipe Up from Edge
+        assertGestureTriggersAction(swipeLeftFromEdge, 1, NAVBAR_WIDTH, 5, 0);
+        // Swipe Down from Edge
+        assertGestureTriggersAction(swipeRightFromEdge, 0, 1, 0, NAVBAR_WIDTH);
     }
 
     @Test
     public void testGesturesCallCorrectActionRTL() throws Exception {
+        doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getWidth();
+        doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getHeight();
         mController.setBarState(true /* isRTL */, NAV_BAR_BOTTOM);
 
         // The swipe gestures below are for LTR, so RTL in portrait will be swapped
@@ -243,20 +285,29 @@
         NavigationGestureAction swipeDown = mockAction(true);
         NavigationGestureAction swipeLeft = mockAction(true);
         NavigationGestureAction swipeRight = mockAction(true);
-        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+        NavigationGestureAction swipeLeftFromEdge = mockAction(true);
+        NavigationGestureAction swipeRightFromEdge = mockAction(true);
+        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
+                swipeRightFromEdge);
 
         // Swipe Up in RTL
         assertGestureTriggersAction(swipeUp, 1, 100, 5, 1);
         // Swipe Down in RTL
         assertGestureTriggersAction(swipeDown, 1, 1, 5, 100);
         // Swipe Left in RTL
-        assertGestureTriggersAction(swipeRight, 100, 1, 5, 1);
+        assertGestureTriggersAction(swipeRight, NAVBAR_WIDTH / 2, 1, 5, 1);
         // Swipe Right in RTL
-        assertGestureTriggersAction(swipeLeft, 1, 1, 100, 5);
+        assertGestureTriggersAction(swipeLeft, NAVBAR_WIDTH / 2, 1, NAVBAR_WIDTH, 0);
+        // Swipe Left from Edge
+        assertGestureTriggersAction(swipeRightFromEdge, NAVBAR_WIDTH, 1, 5, 1);
+        // Swipe Right from Edge
+        assertGestureTriggersAction(swipeLeftFromEdge, 0, 1, NAVBAR_WIDTH, 5);
     }
 
     @Test
     public void testGesturesCallCorrectActionLandscapeRTL() throws Exception {
+        doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getWidth();
+        doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getHeight();
         mController.setBarState(true /* isRTL */, NAV_BAR_RIGHT);
 
         // The swipe gestures below are for LTR, so RTL in landscape will be swapped
@@ -264,20 +315,29 @@
         NavigationGestureAction swipeDown = mockAction(true);
         NavigationGestureAction swipeLeft = mockAction(true);
         NavigationGestureAction swipeRight = mockAction(true);
-        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+        NavigationGestureAction swipeLeftFromEdge = mockAction(true);
+        NavigationGestureAction swipeRightFromEdge = mockAction(true);
+        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
+                swipeRightFromEdge);
 
         // Swipe Up
-        assertGestureTriggersAction(swipeLeft, 1, 100, 5, 1);
+        assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, 1);
         // Swipe Down
-        assertGestureTriggersAction(swipeRight, 1, 1, 5, 100);
+        assertGestureTriggersAction(swipeRight, 1, NAVBAR_WIDTH / 2, 5, NAVBAR_WIDTH);
         // Swipe Left
         assertGestureTriggersAction(swipeUp, 100, 1, 5, 1);
         // Swipe Right
         assertGestureTriggersAction(swipeDown, 1, 1, 100, 5);
+        // Swipe Up from Edge
+        assertGestureTriggersAction(swipeLeftFromEdge, 1, NAVBAR_WIDTH, 5, 0);
+        // Swipe Down from Edge
+        assertGestureTriggersAction(swipeRightFromEdge, 0, 1, 0, NAVBAR_WIDTH);
     }
 
     @Test
     public void testGesturesCallCorrectActionSeascapeRTL() throws Exception {
+        doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getWidth();
+        doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getHeight();
         mController.setBarState(true /* isRTL */, NAV_BAR_LEFT);
 
         // The swipe gestures below are for LTR, so RTL in seascape will be swapped
@@ -285,16 +345,23 @@
         NavigationGestureAction swipeDown = mockAction(true);
         NavigationGestureAction swipeLeft = mockAction(true);
         NavigationGestureAction swipeRight = mockAction(true);
-        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+        NavigationGestureAction swipeLeftFromEdge = mockAction(true);
+        NavigationGestureAction swipeRightFromEdge = mockAction(true);
+        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge,
+                swipeRightFromEdge);
 
         // Swipe Up
-        assertGestureTriggersAction(swipeRight, 1, 100, 5, 1);
+        assertGestureTriggersAction(swipeRight, 1, NAVBAR_WIDTH / 2, 5, 1);
         // Swipe Down
-        assertGestureTriggersAction(swipeLeft, 1, 1, 5, 100);
+        assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, NAVBAR_WIDTH);
         // Swipe Left
         assertGestureTriggersAction(swipeDown, 100, 1, 5, 1);
         // Swipe Right
         assertGestureTriggersAction(swipeUp, 1, 1, 100, 5);
+        // Swipe Up from Edge
+        assertGestureTriggersAction(swipeRightFromEdge, 1, NAVBAR_WIDTH, 5, 0);
+        // Swipe Down from Edge
+        assertGestureTriggersAction(swipeLeftFromEdge, 0, 1, 0, NAVBAR_WIDTH);
     }
 
     @Test
@@ -305,7 +372,8 @@
         // Add enabled gesture action
         NavigationGestureAction action = mockAction(true);
         mController.setGestureActions(action, null /* swipeDownAction */,
-                null /* swipeLeftAction */, null /* swipeRightAction */);
+                null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+                null /* rightEdgeSwipe */);
 
         // Touch down to begin swipe
         MotionEvent downEvent = event(MotionEvent.ACTION_DOWN, 1, 100);
@@ -326,7 +394,8 @@
         NavigationGestureAction action = mockAction(true);
         doReturn(false).when(action).canRunWhenNotificationsShowing();
         mController.setGestureActions(action, null /* swipeDownAction */,
-                null /* swipeLeftAction */, null /* swipeRightAction */);
+                null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+                null /* rightEdgeSwipe */);
 
         // Show the notifications
         doReturn(false).when(mNavigationBarView).isNotificationsFullyCollapsed();
@@ -351,7 +420,8 @@
     public void testActionCannotPerform() throws Exception {
         NavigationGestureAction action = mockAction(true);
         mController.setGestureActions(action, null /* swipeDownAction */,
-                null /* swipeLeftAction */, null /* swipeRightAction */);
+                null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+                null /* rightEdgeSwipe */);
 
         // Cannot perform action
         doReturn(false).when(action).canPerformAction();
@@ -374,13 +444,17 @@
 
     @Test
     public void testQuickScrub() throws Exception {
+        doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getWidth();
+        doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getHeight();
         QuickScrubAction action = spy(new QuickScrubAction(mNavigationBarView, mProxyService));
         mController.setGestureActions(null /* swipeUpAction */, null /* swipeDownAction */,
-                null /* swipeLeftAction */, action);
+                null /* swipeLeftAction */, action, null /* leftEdgeSwipe */,
+                null /* rightEdgeSwipe */);
+        int x = NAVBAR_WIDTH / 2;
         int y = 20;
 
         // Set the layout and other padding to make sure the scrub fraction is calculated correctly
-        action.onLayout(true, 0, 0, 400, 100);
+        action.onLayout(true, 0, 0, NAVBAR_WIDTH, NAVBAR_HEIGHT);
         doReturn(0).when(mNavigationBarView).getPaddingLeft();
         doReturn(0).when(mNavigationBarView).getPaddingRight();
         doReturn(0).when(mNavigationBarView).getPaddingStart();
@@ -393,14 +467,14 @@
         doReturn(true).when(mNavigationBarView).isQuickScrubEnabled();
 
         // Touch down
-        MotionEvent downEvent = event(MotionEvent.ACTION_DOWN, 0, y);
+        MotionEvent downEvent = event(MotionEvent.ACTION_DOWN, x, y);
         assertFalse(touch(downEvent));
         assertNull(mController.getCurrentAction());
         verify(mProxy, times(1)).onPreMotionEvent(mNavigationBarView.getDownHitTarget());
         verify(mProxy, times(1)).onMotionEvent(downEvent);
 
         // Move to start trigger action from gesture
-        MotionEvent moveEvent1 = event(MotionEvent.ACTION_MOVE, 100, y);
+        MotionEvent moveEvent1 = event(MotionEvent.ACTION_MOVE, x + 100, y);
         assertTrue(touch(moveEvent1));
         assertEquals(action, mController.getCurrentAction());
         verify(action, times(1)).onGestureStart(moveEvent1);
@@ -410,11 +484,13 @@
         verify(mProxy, never()).onMotionEvent(moveEvent1);
 
         // Move again for scrub
-        MotionEvent moveEvent2 = event(MotionEvent.ACTION_MOVE, 200, y);
+        float fraction = 3f / 4;
+        x = (int) (NAVBAR_WIDTH * fraction);
+        MotionEvent moveEvent2 = event(MotionEvent.ACTION_MOVE, x, y);
         assertTrue(touch(moveEvent2));
         assertEquals(action, mController.getCurrentAction());
-        verify(action, times(1)).onGestureMove(200, y);
-        verify(mProxy, times(1)).onQuickScrubProgress(1f / 2);
+        verify(action, times(1)).onGestureMove(x, y);
+        verify(mProxy, times(1)).onQuickScrubProgress(fraction);
         verify(mProxy, never()).onMotionEvent(moveEvent2);
 
         // Action up
@@ -430,7 +506,8 @@
     public void testQuickStep() throws Exception {
         QuickStepAction action = new QuickStepAction(mNavigationBarView, mProxyService);
         mController.setGestureActions(action, null /* swipeDownAction */,
-                null /* swipeLeftAction */, null /* swipeRightAction */);
+                null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+                null /* rightEdgeSwipe */);
 
         // Notifications are up, should prevent quickstep
         doReturn(false).when(mNavigationBarView).isNotificationsFullyCollapsed();
@@ -466,7 +543,8 @@
     public void testLongPressPreventDetection() throws Exception {
         NavigationGestureAction action = mockAction(true);
         mController.setGestureActions(action, null /* swipeDownAction */,
-                null /* swipeLeftAction */, null /* swipeRightAction */);
+                null /* swipeLeftAction */, null /* swipeRightAction */, null /* leftEdgeSwipe */,
+                null /* rightEdgeSwipe */);
 
         // Start the drag up
         assertFalse(touch(MotionEvent.ACTION_DOWN, 100, 1));
@@ -488,23 +566,21 @@
 
     @Test
     public void testHitTargetDragged() throws Exception {
-        final int navbarWidth = 1000;
-        final int navbarHeight = 1000;
         ButtonDispatcher button = mock(ButtonDispatcher.class);
-        FakeLocationView buttonView = spy(new FakeLocationView(mContext, navbarWidth / 2,
-                navbarHeight / 2));
+        FakeLocationView buttonView = spy(new FakeLocationView(mContext, NAVBAR_WIDTH / 2,
+                NAVBAR_HEIGHT / 2));
         doReturn(buttonView).when(button).getCurrentView();
 
         NavigationGestureAction action = mockAction(true);
-        mController.setGestureActions(action, action, action, action);
+        mController.setGestureActions(action, action, action, action, action, action);
 
         // Setup getting the hit target
         doReturn(HIT_TARGET_HOME).when(action).requiresTouchDownHitTarget();
-        doReturn(true).when(action).requiresDragWithHitTarget();
+        doReturn(true).when(action).allowHitTargetToMoveOverDrag();
         doReturn(HIT_TARGET_HOME).when(mNavigationBarView).getDownHitTarget();
         doReturn(button).when(mNavigationBarView).getHomeButton();
-        doReturn(navbarWidth).when(mNavigationBarView).getWidth();
-        doReturn(navbarHeight).when(mNavigationBarView).getHeight();
+        doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getWidth();
+        doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getHeight();
 
         // Portrait
         assertGestureDragsHitTargetAllDirections(buttonView, false /* isRTL */, NAV_BAR_BOTTOM);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 27123e4..02f8949 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -70,7 +70,7 @@
                 mock(NotificationPanelView.class), mock(HeadsUpManagerPhone.class),
                 statusBarWindowView, mock(NotificationListContainerViewGroup.class),
                 mock(DozeScrimController.class), mock(ScrimController.class),
-                mock(ActivityLaunchAnimator.class));
+                mock(ActivityLaunchAnimator.class), mock(StatusBarKeyguardViewManager.class));
     }
 
     @Test
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml b/packages/overlays/ExperimentNavigationBarDefaultOverlay/res/values-en-rXC/strings.xml
similarity index 65%
copy from packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
copy to packages/overlays/ExperimentNavigationBarDefaultOverlay/res/values-en-rXC/strings.xml
index 6a1ce41..c5ed415 100644
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarDefaultOverlay/res/values-en-rXC/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Úzky navigačný panel (experiment)"</string>
+    <string name="experiment_navigationbar_overlay" msgid="3475628315769912732">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎Default Navigation Bar Experiment (48dp)‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-af/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-af/strings.xml
deleted file mode 100644
index 21a0003..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-af/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperiment met dun navigasiebalk"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-am/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-am/strings.xml
deleted file mode 100644
index 6a7d644..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-am/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ቀጭን የአሰሳ አሞሌ ሙከራ"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ar/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ar/strings.xml
deleted file mode 100644
index 2cebf40..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ar/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"تجربة شريط التنقُّل النحيف"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-az/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-az/strings.xml
deleted file mode 100644
index 266c051..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-az/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Sabit Naviqasiya Paneli Təcrübəsi"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-b+sr+Latn/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index dc57a3f..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperiment sa tankom trakom za navigaciju"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-be/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-be/strings.xml
deleted file mode 100644
index 8b53bcd..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-be/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Эксперымент з тонкай панэллю навігацыі"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bg/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bg/strings.xml
deleted file mode 100644
index 4bf000e..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bg/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Експеримент с тънка лента за навигация"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bs/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bs/strings.xml
deleted file mode 100644
index 9814209..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bs/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperiment s tankom trakom za navigaciju"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ca/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ca/strings.xml
deleted file mode 100644
index 4a9b598..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ca/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experiment amb barra de navegació fina"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-cs/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-cs/strings.xml
deleted file mode 100644
index d923a3c..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-cs/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Úzký navigační panel (experiment)"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-da/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-da/strings.xml
deleted file mode 100644
index 12bb2f2..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-da/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Test med smal navigationslinje"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-de/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-de/strings.xml
deleted file mode 100644
index 960a7d9..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-de/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experiment mit schmaler Navigationsleiste"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-el/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-el/strings.xml
deleted file mode 100644
index 119b7e6..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-el/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Πείραμα λεπτής γραμμής πλοήγησης"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rAU/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rAU/strings.xml
deleted file mode 100644
index 5ebf403..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Slim Navigation Bar Experiment"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rCA/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rCA/strings.xml
deleted file mode 100644
index 5ebf403..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Slim Navigation Bar Experiment"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rGB/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rGB/strings.xml
deleted file mode 100644
index 5ebf403..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Slim Navigation Bar Experiment"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rIN/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rIN/strings.xml
deleted file mode 100644
index 5ebf403..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Slim Navigation Bar Experiment"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rXC/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rXC/strings.xml
index 79884ce..40d9fbc 100644
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rXC/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rXC/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‎‏‏‎‎‎‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‎Slim Navigation Bar Experiment‎‏‎‎‏‎"</string>
+    <string name="experiment_navigationbar_overlay" msgid="9207872199884142345">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‏‎Slim Navigation Bar Experiment (24dp)‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es-rUS/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es-rUS/strings.xml
deleted file mode 100644
index 00b0444..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experimento de barra de navegación delgada"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es/strings.xml
deleted file mode 100644
index 58bdaa2..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experimento de barra navegación delgada"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-et/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-et/strings.xml
deleted file mode 100644
index 4c5023c..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-et/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Kitsa navigeerimisriba katse"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-eu/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-eu/strings.xml
deleted file mode 100644
index fc16eeb..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-eu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Nabigazio-barra finaren esperimentua"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fa/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fa/strings.xml
deleted file mode 100644
index e4246d7..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fa/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"آزمایش نوار پیمایش باریک"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fi/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fi/strings.xml
deleted file mode 100644
index 9385a47..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fi/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Ohuen navigointipalkin kokeilu"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr-rCA/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr-rCA/strings.xml
deleted file mode 100644
index d22848b..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Expérience de barre de navigation mince"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr/strings.xml
deleted file mode 100644
index cfa1db2..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Test relatif à la barre de navigation fine"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-gl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-gl/strings.xml
deleted file mode 100644
index d2194ce..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-gl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experimento de barra de navegación estreita"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hi/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hi/strings.xml
deleted file mode 100644
index d51cee3..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hi/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"स्लिम नेविगेशन बार प्रयोग"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hr/strings.xml
deleted file mode 100644
index 410c58e..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperiment s tankom navigacijskom trakom"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hu/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hu/strings.xml
deleted file mode 100644
index d7eafed..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Kísérleti keskeny navigációs sáv"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hy/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hy/strings.xml
deleted file mode 100644
index b0200ca..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hy/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Նավարկման նեղ գոտու փորձարկում"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-in/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-in/strings.xml
deleted file mode 100644
index 3e0bded..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-in/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperimen Menu Navigasi Ramping"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-is/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-is/strings.xml
deleted file mode 100644
index 03ccaf3..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-is/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Tilraun með þunna yfirlitsstiku"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-it/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-it/strings.xml
deleted file mode 100644
index f7c5d253..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-it/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Esperimento Barra di navigazione sottile"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-iw/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-iw/strings.xml
deleted file mode 100644
index 0d0ec2c..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-iw/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ניסוי של סרגל ניווט דק"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ja/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ja/strings.xml
deleted file mode 100644
index a3d6874..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ja/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"スリム ナビゲーション バー テスト"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ka/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ka/strings.xml
deleted file mode 100644
index ffddf3b..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ka/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ნავიგაციის მჭიდრო ზოლის ექსპერიმენტი"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-kk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-kk/strings.xml
deleted file mode 100644
index f34ac08..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-kk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Жіңішке навигация жолағы (эксперимент)"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-km/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-km/strings.xml
deleted file mode 100644
index 114a782..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-km/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ការពិសោធ​នៃ​របាររុករក​ស្ដើង"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ko/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ko/strings.xml
deleted file mode 100644
index fca02c3..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ko/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"슬림한 탐색 메뉴 실험"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ky/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ky/strings.xml
deleted file mode 100644
index 449de4f..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ky/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Чакан чабыттоо тилкесин сыноо"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lo/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lo/strings.xml
deleted file mode 100644
index 6ec48ca..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lo/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ການທົດລອງແຖບການນຳທາງແບບບາງ"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lt/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lt/strings.xml
deleted file mode 100644
index 1df54aa..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lt/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Plonos naršymo juostos eksperimentas"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lv/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lv/strings.xml
deleted file mode 100644
index 5c6c565..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lv/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Plānas navigācijas joslas eksperiments"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mk/strings.xml
deleted file mode 100644
index 3517813..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Експеримент со тенка лента за навигација"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mn/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mn/strings.xml
deleted file mode 100644
index a2282c4..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Нимгэн навигацийн самбарын туршилт"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mr/strings.xml
deleted file mode 100644
index c714370..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"स्लिम नॅव्हिगेशन बार प्रयोग"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ms/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ms/strings.xml
deleted file mode 100644
index 68f831e..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ms/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Percubaan Bar Navigasi Langsing"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-my/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-my/strings.xml
deleted file mode 100644
index 84db279..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-my/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ပါးလွှာသော လမ်းညွှန်ဘား စမ်းသပ်မှု"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nb/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nb/strings.xml
deleted file mode 100644
index e1ff863..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nb/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperiment med tynn navigasjonsrad"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nl/strings.xml
deleted file mode 100644
index 01190bc..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experiment voor smalle navigatiebalk"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pl/strings.xml
deleted file mode 100644
index 1742aad..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperyment z wąskim paskiem nawigacyjnym"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rBR/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rBR/strings.xml
deleted file mode 100644
index 22194b7..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rBR/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experimento de barra de navegação fina"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rPT/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rPT/strings.xml
deleted file mode 100644
index f6c0309..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experiência de barra de navegação fina"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt/strings.xml
deleted file mode 100644
index 22194b7..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experimento de barra de navegação fina"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ro/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ro/strings.xml
deleted file mode 100644
index e1655f2..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ro/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experiment cu bară de navigare subțire"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ru/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ru/strings.xml
deleted file mode 100644
index cac66dc..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ru/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Узкая панель навигации (эксперимент)"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sl/strings.xml
deleted file mode 100644
index beab7b6..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Preizkus z vitko vrstico za krmarjenje"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sq/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sq/strings.xml
deleted file mode 100644
index b7a28d5..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sq/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperimenti i shiritit të hollë të navigimit"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sr/strings.xml
deleted file mode 100644
index 048f649..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Експеримент са танком траком за навигацију"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sv/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sv/strings.xml
deleted file mode 100644
index b94438f..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sv/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experimentellt tunt navigeringsfält"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sw/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sw/strings.xml
deleted file mode 100644
index 3a5a73c..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sw/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Jaribio la Sehemu ya Viungo Muhimu Inayoweza Kupunguzwa"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-th/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-th/strings.xml
deleted file mode 100644
index 945297b..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-th/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"การทดสอบแถบนำทางแบบบาง"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tl/strings.xml
deleted file mode 100644
index 0c8087c..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperimentong Slim na Navigation Bar"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tr/strings.xml
deleted file mode 100644
index a3ca754..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"İnce Gezinme Çubuğu Denemesi"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uk/strings.xml
deleted file mode 100644
index 656c4a9..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Експеримент із тонкою панеллю навігації"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ur/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ur/strings.xml
deleted file mode 100644
index bcd6bc3..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ur/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"سلم نیویگیشن بار کا تجربہ"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uz/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uz/strings.xml
deleted file mode 100644
index 0d40981..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uz/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Ingichka navigatsiya paneli tajribasi"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-vi/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-vi/strings.xml
deleted file mode 100644
index dad56b4..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-vi/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Thử nghiệm thanh điều hướng mỏng"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rCN/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rCN/strings.xml
deleted file mode 100644
index b2602e0..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"精简导航栏实验"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rHK/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rHK/strings.xml
deleted file mode 100644
index d5259d3..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"精簡導覽列實驗"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rTW/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 6586a57..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"細長導覽列實驗"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zu/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zu/strings.xml
deleted file mode 100644
index 12d04d3..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * 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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Ukuhlolwa kwebha yokuzula encane"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim32Overlay/res/values-en-rXC/strings.xml
similarity index 65%
rename from packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
rename to packages/overlays/ExperimentNavigationBarSlim32Overlay/res/values-en-rXC/strings.xml
index 6a1ce41..ca8c4fa 100644
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim32Overlay/res/values-en-rXC/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Úzky navigačný panel (experiment)"</string>
+    <string name="experiment_navigationbar_overlay" msgid="2616250866244714325">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎Slim Navigation Bar Experiment (32dp)‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim40Overlay/res/values-en-rXC/strings.xml
similarity index 65%
copy from packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
copy to packages/overlays/ExperimentNavigationBarSlim40Overlay/res/values-en-rXC/strings.xml
index 6a1ce41..9209c2b 100644
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim40Overlay/res/values-en-rXC/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Úzky navigačný panel (experiment)"</string>
+    <string name="experiment_navigationbar_overlay" msgid="6415947279345789008">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‎‎‎‎‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎Slim Navigation Bar Experiment (40dp)‎‏‎‎‏‎"</string>
 </resources>
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 3e07d12..dec0c29 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6604,6 +6604,23 @@
     // OS: Q
     NOTIFICATION_DIRECT_REPLY_ACTION = 1590;
 
+    // OPEN: Settings > Developer options > Disable > Info dialog
+    // CATEGORY: SETTINGS
+    // OS: Q
+    DIALOG_DISABLE_DEVELOPMENT_OPTIONS = 1591;
+
+    // Tag for an ACTION: QS -> Tile click / Secondary click / long press
+    //    indicating the StatusBarState when menu was pulled down
+    // CATEGORY: QUICK_SETTINGS
+    // OS: Q
+    FIELD_STATUS_BAR_STATE = 1592;
+
+    // Tag for an ACTION: QS -> Tile click / Secondary click / long press
+    //    indicating whether current state is full QS
+    // CATEGORY: QUICK_SETTINGS
+    // OS: Q
+    FIELD_IS_FULL_QS = 1593;
+
     // ---- End Q Constants, all Q constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/services/Android.bp b/services/Android.bp
index 3390438..58a0997 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -21,9 +21,9 @@
         "services.autofill",
         "services.backup",
         "services.companion",
+        "services.contentcapture",
         "services.coverage",
         "services.devicepolicy",
-        "services.intelligence",
         "services.midi",
         "services.net",
         "services.print",
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 944ee33..e8887e7 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -74,7 +74,6 @@
 import com.android.server.LocalServices;
 import com.android.server.autofill.ui.AutoFillUI;
 import com.android.server.infra.AbstractMasterSystemService;
-import com.android.server.intelligence.IntelligenceManagerInternal;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -100,6 +99,7 @@
 
     private static final Object sLock = AutofillManagerService.class;
 
+    private static final int MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS = 1_000 * 60 * 2; // 2 minutes
 
     /**
      * IME supports Smart Suggestions.
@@ -155,7 +155,7 @@
 
     private final AutofillCompatState mAutofillCompatState = new AutofillCompatState();
     private final LocalService mLocalService = new LocalService();
-    final IntelligenceManagerInternal mIntelligenceManagerInternal;
+    private final ActivityManagerInternal mAm;
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -184,7 +184,7 @@
     public AutofillManagerService(Context context) {
         super(context, UserManager.DISALLOW_AUTOFILL);
         mUi = new AutoFillUI(ActivityThread.currentActivityThread().getSystemUiContext());
-        mIntelligenceManagerInternal = LocalServices.getService(IntelligenceManagerInternal.class);
+        mAm = LocalServices.getService(ActivityManagerInternal.class);
 
         setLogLevelFromSettings();
         setMaxPartitionsFromSettings();
@@ -288,6 +288,11 @@
         return mSupportedSmartSuggestionModes;
     }
 
+    // Called by AutofillManagerServiceImpl, doesn't need to check permission
+    boolean isInstantServiceAllowed() {
+        return mAllowInstantService;
+    }
+
     // Called by Shell command.
     void destroySessions(@UserIdInt int userId, IResultReceiver receiver) {
         Slog.i(TAG, "destroySessions() for userId " + userId);
@@ -502,6 +507,39 @@
         sFullScreenMode = mode;
     }
 
+    // Called by Shell command.
+    void setTemporaryAugmentedAutofillService(@UserIdInt int userId, @NonNull String serviceName,
+            int durationMs) {
+        Slog.i(mTag, "setTemporaryAugmentedAutofillService(" + userId + ") to " + serviceName
+                + " for " + durationMs + "ms");
+        enforceCallingPermissionForManagement();
+
+        Preconditions.checkNotNull(serviceName);
+        if (durationMs > MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS) {
+            throw new IllegalArgumentException("Max duration is "
+                    + MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS + " (called with " + durationMs + ")");
+        }
+
+        synchronized (mLock) {
+            final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
+            if (service != null) {
+                service.mAugmentedAutofillResolver.setTemporaryServiceLocked(serviceName,
+                        durationMs);
+            }
+        }
+    }
+
+    // Called by Shell command
+    void resetTemporaryAugmentedAutofillService(@UserIdInt int userId) {
+        enforceCallingPermissionForManagement();
+        synchronized (mLock) {
+            final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
+            if (service != null) {
+                service.mAugmentedAutofillResolver.resetTemporaryServiceLocked();
+            }
+        }
+    }
+
     private void setLoggingLevelsLocked(boolean debug, boolean verbose) {
         com.android.server.autofill.Helper.sDebug = debug;
         android.view.autofill.Helper.sDebug = debug;
@@ -877,14 +915,9 @@
                 throw new IllegalArgumentException(packageName + " is not a valid package", e);
             }
 
-            // TODO(b/113281366): rather than always call AM here, call it on demand on
-            // getPreviousSessionsLocked()? That way we save space / time here, and don't set
-            // a callback on AM unnecessarily (see TODO below :-)
-            final ActivityManagerInternal am = LocalServices
-                    .getService(ActivityManagerInternal.class);
             // TODO(b/113281366): add a callback method on AM to be notified when a task is finished
             // so we can clean up sessions kept alive
-            final int taskId = am.getTaskIdForActivity(activityToken, false);
+            final int taskId = mAm.getTaskIdForActivity(activityToken, false);
             final int sessionId;
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 3945c23..5a0d12c 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -73,8 +73,11 @@
 import com.android.server.LocalServices;
 import com.android.server.autofill.AutofillManagerService.AutofillCompatState;
 import com.android.server.autofill.AutofillManagerService.SmartSuggestionMode;
+import com.android.server.autofill.RemoteAugmentedAutofillService.RemoteAugmentedAutofillServiceCallbacks;
 import com.android.server.autofill.ui.AutoFillUI;
 import com.android.server.infra.AbstractPerUserSystemService;
+import com.android.server.infra.AbstractRemoteService;
+import com.android.server.infra.FrameworkResourcesServiceNameResolver;
 import com.android.server.infra.SecureSettingsServiceNameResolver;
 
 import java.io.PrintWriter;
@@ -152,6 +155,19 @@
     /** When was {@link PruneTask} last executed? */
     private long mLastPrune = 0;
 
+    /**
+     * Object used to set the name of the augmented autofill service.
+     */
+    @NonNull
+    final FrameworkResourcesServiceNameResolver mAugmentedAutofillResolver;
+
+    /**
+     * Reference to the {@link RemoteAugmentedAutofillService}, is set on demand.
+     */
+    @GuardedBy("mLock")
+    @Nullable
+    private RemoteAugmentedAutofillService mRemoteAugmentedAutofillService;
+
     AutofillManagerServiceImpl(AutofillManagerService master, Object lock, LocalLog requestsHistory,
             LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
             AutofillCompatState autofillCompatState, boolean disabled) {
@@ -164,6 +180,12 @@
         mUi = ui;
         mFieldClassificationStrategy = new FieldClassificationStrategy(getContext(), userId);
         mAutofillCompatState = autofillCompatState;
+
+        mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(master.getContext(),
+                userId, lock, com.android.internal.R.string.config_defaultAugmentedAutofillService);
+        mAugmentedAutofillResolver.setOnTemporaryServiceNameChangedCallback(
+                () -> updateRemoteAugmentedAutofillService());
+
         updateLocked(disabled);
     }
 
@@ -851,6 +873,12 @@
         }
         pw.print(prefix); pw.print("Default component: "); pw.println(getContext()
                 .getString(R.string.config_defaultAutofillService));
+        pw.print(prefix); pw.print("mAugmentedAutofillNamer: ");
+        mAugmentedAutofillResolver.dumpShortLocked(pw); pw.println();
+        if (mRemoteAugmentedAutofillService != null) {
+            pw.print(prefix); pw.println("RemoteAugmentedAutofillService: ");
+            mRemoteAugmentedAutofillService.dump(prefix2, pw);
+        }
         pw.print(prefix); pw.print("Field classification enabled: ");
             pw.println(isFieldClassificationEnabledLocked());
         pw.print(prefix); pw.print("Compat pkgs: ");
@@ -992,6 +1020,52 @@
         return null;
     }
 
+    @GuardedBy("mLock")
+    @Nullable RemoteAugmentedAutofillService getRemoteAugmentedAutofillServiceLocked() {
+        if (mRemoteAugmentedAutofillService == null) {
+            final String serviceName = mAugmentedAutofillResolver.getServiceNameLocked();
+            if (serviceName == null) {
+                if (mMaster.verbose) {
+                    Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): not set");
+                }
+                return null;
+            }
+            final ComponentName componentName = RemoteAugmentedAutofillService.getComponentName(
+                    getContext(), serviceName, mUserId,
+                    mAugmentedAutofillResolver.isTemporaryLocked());
+            if (componentName == null) return null;
+            if (sVerbose) {
+                Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): " + componentName);
+            }
+
+            mRemoteAugmentedAutofillService = new RemoteAugmentedAutofillService(getContext(),
+                    componentName, mUserId, new RemoteAugmentedAutofillServiceCallbacks() {
+                        @Override
+                        public void onServiceDied(
+                                AbstractRemoteService<? extends AbstractRemoteService<?>> service) {
+                            // TODO(b/111330312): properly implement
+                            Slog.w(TAG, "remote augmented autofill service died");
+                        }
+                    }, mMaster.isInstantServiceAllowed(), mMaster.verbose);
+        }
+
+        return mRemoteAugmentedAutofillService;
+    }
+
+    /**
+     * Called when the {@link #mAugmentedAutofillResolver} changed (among other places).
+     */
+    private void updateRemoteAugmentedAutofillService() {
+        final String serviceName = mAugmentedAutofillResolver.getServiceNameLocked();
+        if (serviceName == null) {
+            if (sVerbose) Slog.v(TAG, "updateRemoteAugmentedAutofillService(): time's up!");
+            if (mRemoteAugmentedAutofillService != null) {
+                mRemoteAugmentedAutofillService.destroy();
+                mRemoteAugmentedAutofillService = null;
+            }
+        }
+    }
+
     private void sendStateToClients(boolean resetClient) {
         final RemoteCallbackList<IAutoFillManagerClient> clients;
         final int userClientCount;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index 522280e..35c5102 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -104,6 +104,11 @@
             pw.println("  set bind-instant-service-allowed [true | false]");
             pw.println("    Sets whether binding to services provided by instant apps is allowed");
             pw.println("");
+            pw.println("  set temporary-augmented-service USER_ID [COMPONENT_NAME DURATION]");
+            pw.println("    Temporarily (for DURATION ms) changes the augmented autofill service "
+                    + "implementation.");
+            pw.println("    To reset, call with just the USER_ID argument.");
+            pw.println("");
             pw.println("  list sessions [--user USER_ID]");
             pw.println("    Lists all pending sessions.");
             pw.println("");
@@ -151,6 +156,8 @@
                 return setFullScreenMode(pw);
             case "bind-instant-service-allowed":
                 return setBindInstantService(pw);
+            case "temporary-augmented-service":
+                return setTemporaryAugmentedService(pw);
             default:
                 pw.println("Invalid set: " + what);
                 return -1;
@@ -293,6 +300,20 @@
         }
     }
 
+    private int setTemporaryAugmentedService(PrintWriter pw) {
+        final int userId = getNextIntArgRequired();
+        final String serviceName = getNextArg();
+        if (serviceName == null) {
+            mService.resetTemporaryAugmentedAutofillService(userId);
+            return 0;
+        }
+        final int duration = getNextIntArgRequired();
+        mService.setTemporaryAugmentedAutofillService(userId, serviceName, duration);
+        pw.println("AugmentedAutofillService temporarily set to " + serviceName + " for "
+                + duration + "ms");
+        return 0;
+    }
+
     private int requestDestroy(PrintWriter pw) {
         if (!isNextArgSessions(pw)) {
             return -1;
@@ -371,4 +392,8 @@
         }
         return UserHandle.USER_ALL;
     }
+
+    private int getNextIntArgRequired() {
+        return Integer.parseInt(getNextArgRequired());
+    }
 }
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
new file mode 100644
index 0000000..222888c
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -0,0 +1,235 @@
+/*
+ * 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.server.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.service.autofill.augmented.AugmentedAutofillService;
+import android.service.autofill.augmented.IAugmentedAutofillService;
+import android.service.autofill.augmented.IFillCallback;
+import android.text.format.DateUtils;
+import android.util.Slog;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
+import android.view.autofill.IAutoFillManagerClient;
+
+import com.android.internal.os.IResultReceiver;
+import com.android.server.infra.AbstractSinglePendingRequestRemoteService;
+
+final class RemoteAugmentedAutofillService
+        extends AbstractSinglePendingRequestRemoteService<RemoteAugmentedAutofillService> {
+
+    private static final String TAG = RemoteAugmentedAutofillService.class.getSimpleName();
+
+    // TODO(b/117779333): changed it so it's permanentely bound
+    private static final long TIMEOUT_IDLE_BIND_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
+    private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
+
+    private final RemoteAugmentedAutofillServiceCallbacks mCallbacks;
+    private IAugmentedAutofillService mService;
+
+    RemoteAugmentedAutofillService(Context context, ComponentName serviceName,
+            int userId, RemoteAugmentedAutofillServiceCallbacks callbacks,
+            boolean bindInstantServiceAllowed, boolean verbose) {
+        super(context, AugmentedAutofillService.SERVICE_INTERFACE, serviceName, userId, callbacks,
+                bindInstantServiceAllowed, verbose);
+        mCallbacks = callbacks;
+    }
+
+    @Nullable
+    public static ComponentName getComponentName(@NonNull Context context,
+            @NonNull String componentName, @UserIdInt int userId, boolean isTemporary) {
+        int flags = PackageManager.GET_META_DATA;
+        if (!isTemporary) {
+            flags |= PackageManager.MATCH_SYSTEM_ONLY;
+        }
+
+        final ComponentName serviceComponent;
+        ServiceInfo serviceInfo = null;
+        try {
+            serviceComponent = ComponentName.unflattenFromString(componentName);
+            serviceInfo = AppGlobals.getPackageManager().getServiceInfo(serviceComponent, flags,
+                    userId);
+            if (serviceInfo == null) {
+                Slog.e(TAG, "Bad service name for flags " + flags + ": " + componentName);
+                return null;
+            }
+        } catch (Exception e) {
+            Slog.e(TAG, "Error getting service info for '" + componentName + "': " + e);
+            return null;
+        }
+        return serviceComponent;
+    }
+
+    @Override // from AbstractRemoteService
+    protected IInterface getServiceInterface(IBinder service) {
+        mService = IAugmentedAutofillService.Stub.asInterface(service);
+        return mService;
+    }
+
+    @Override // from AbstractRemoteService
+    protected long getTimeoutIdleBindMillis() {
+        return TIMEOUT_IDLE_BIND_MILLIS;
+    }
+
+    @Override // from AbstractRemoteService
+    protected long getRemoteRequestMillis() {
+        return TIMEOUT_REMOTE_REQUEST_MILLIS;
+    }
+
+    /**
+     * Called by {@link Session} to request augmented autofill.
+     */
+    public void onRequestAutofillLocked(int sessionId, @NonNull IAutoFillManagerClient client,
+            int taskId, @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId,
+            @Nullable AutofillValue focusedValue) {
+        cancelScheduledUnbind();
+        scheduleRequest(new PendingAutofillRequest(this, sessionId, client, taskId,
+                activityComponent, focusedId, focusedValue));
+    }
+
+    /**
+     * Called by {@link Session} when it's time to destroy all augmented autofill requests.
+     */
+    public void onDestroyAutofillWindowsRequest(int sessionId) {
+        cancelScheduledUnbind();
+        scheduleRequest(new PendingDestroyAutofillWindowsRequest(this, sessionId));
+    }
+
+    private abstract static class MyPendingRequest
+            extends PendingRequest<RemoteAugmentedAutofillService> {
+        protected final int mSessionId;
+
+        private MyPendingRequest(@NonNull RemoteAugmentedAutofillService service, int sessionId) {
+            super(service);
+            mSessionId = sessionId;
+        }
+    }
+
+    private static final class PendingAutofillRequest extends MyPendingRequest {
+        private final @NonNull AutofillId mFocusedId;
+        private final @Nullable AutofillValue mFocusedValue;
+        private final @NonNull IAutoFillManagerClient mClient;
+        private final @NonNull ComponentName mActivityComponent;
+        private final int mTaskId;
+        private final long mRequestTime = SystemClock.elapsedRealtime();
+        private final @NonNull IFillCallback mCallback;
+
+        protected PendingAutofillRequest(@NonNull RemoteAugmentedAutofillService service,
+                int sessionId, @NonNull IAutoFillManagerClient client, int taskId,
+                @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId,
+                @Nullable AutofillValue focusedValue) {
+            super(service, sessionId);
+            mClient = client;
+            mTaskId = taskId;
+            mActivityComponent = activityComponent;
+            mFocusedId = focusedId;
+            mFocusedValue = focusedValue;
+            mCallback = new IFillCallback.Stub() {
+                @Override
+                public void onSuccess() {
+                    if (!finish()) return;
+                    // NOTE: so far we don't need notify RemoteAugmentedAutofillServiceCallbacks
+                }
+            };
+        }
+
+        @Override
+        public void run() {
+            final RemoteAugmentedAutofillService remoteService = getService();
+            if (remoteService == null) return;
+
+            final IResultReceiver receiver = new IResultReceiver.Stub() {
+
+                @Override
+                public void send(int resultCode, Bundle resultData) throws RemoteException {
+                    final IBinder realClient = resultData
+                            .getBinder(AutofillManager.EXTRA_AUGMENTED_AUTOFILL_CLIENT);
+                    remoteService.mService.onFillRequest(mSessionId, realClient, mTaskId,
+                            mActivityComponent, mFocusedId, mFocusedValue, mRequestTime, mCallback);
+                }
+            };
+
+            // TODO(b/111330312): set cancellation signal, timeout (from both mClient and service),
+            // cache IAugmentedAutofillManagerClient reference, etc...
+            try {
+                mClient.getAugmentedAutofillClient(receiver);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "exception handling getAugmentedAutofillClient() for "
+                        + mSessionId + ": " + e);
+                finish();
+            }
+        }
+
+        @Override
+        protected void onTimeout(RemoteAugmentedAutofillService remoteService) {
+            Slog.wtf(TAG, "timed out: " + this);
+            // NOTE: so far we don't need notify RemoteAugmentedAutofillServiceCallbacks
+            finish();
+        }
+
+    }
+
+    private static final class PendingDestroyAutofillWindowsRequest extends MyPendingRequest {
+
+        protected PendingDestroyAutofillWindowsRequest(
+                @NonNull RemoteAugmentedAutofillService service, @NonNull int sessionId) {
+            super(service, sessionId);
+        }
+
+        @Override
+        public void run() {
+            final RemoteAugmentedAutofillService remoteService = getService();
+            if (remoteService == null) return;
+
+            try {
+                remoteService.mService.onDestroyFillWindowRequest(mSessionId);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "exception handling onDestroyAutofillWindowsRequest() for "
+                        + mSessionId + ": " + e);
+            } finally {
+                // Service is not calling back, so we finish right away.
+                finish();
+            }
+        }
+
+        @Override
+        protected void onTimeout(RemoteAugmentedAutofillService remoteService) {
+            // Should not happen because we called finish() on run(), although currently it might
+            // be called if the service is destroyed while showing it.
+            Slog.e(TAG, "timed out: " + this);
+        }
+    }
+
+    public interface RemoteAugmentedAutofillServiceCallbacks extends VultureCallback {
+        // NOTE: so far we don't need to notify the callback implementation (an inner class on
+        // AutofillManagerServiceImpl) of the request results (success, timeouts, etc..), so this
+        // callback interface is empty.
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index fb64cb2..d76a5df 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -99,8 +99,6 @@
 import com.android.server.autofill.ui.AutoFillUI;
 import com.android.server.autofill.ui.PendingUi;
 import com.android.server.infra.AbstractRemoteService;
-import com.android.server.intelligence.IntelligenceManagerInternal;
-import com.android.server.intelligence.IntelligenceManagerInternal.AugmentedAutofillCallback;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -248,9 +246,18 @@
     @GuardedBy("mLock")
     private final SparseArray<LogMaker> mRequestLogs = new SparseArray<>(1);
 
+    /**
+     * Destroys the augmented Autofill UI.
+     */
+    // TODO(b/111330312): this runnable is called when the Autofill session is destroyed, the
+    // main reason being the cases where user tap HOME.
+    // Right now it's completely destroying the UI, but we need to decide whether / how to
+    // properly recover it later (for example, if the user switches back to the activity,
+    // should it be restored? Right not it kind of is, because Autofill's Session trigger a
+    // new FillRequest, which in turn triggers the Augmented Autofill request again)
     @GuardedBy("mLock")
     @Nullable
-    private AugmentedAutofillCallback mAugmentedAutofillCallback;
+    private Runnable mAugmentedAutofillDestroyer;
 
     /**
      * Receiver of assist data from the app's {@link Activity}.
@@ -2516,8 +2523,8 @@
 
         // The default autofill service cannot fullfill the request, let's check if the intelligence
         // service can.
-        mAugmentedAutofillCallback = triggerAugmentedAutofillLocked();
-        if (mAugmentedAutofillCallback == null) {
+        mAugmentedAutofillDestroyer = triggerAugmentedAutofillLocked();
+        if (mAugmentedAutofillDestroyer == null) {
             if (sVerbose) {
                 Slog.v(TAG, "canceling session " + id + " when server returned null and there is no"
                         + " AugmentedAutofill for user");
@@ -2539,21 +2546,22 @@
     /**
      * Tries to trigger Augmented Autofill when the standard service could not fulfill a request.
      *
-     * @return callback to the Augmented Autofill service, or {@code null} if not supported.
+     * @return callback to destroy the autofill UI, or {@code null} if not supported.
      */
     // TODO(b/111330312): might need to call it in other places, like when the service returns a
     // non-null response but without datasets (for example, just SaveInfo)
     @GuardedBy("mLock")
-    private AugmentedAutofillCallback triggerAugmentedAutofillLocked() {
+    private Runnable triggerAugmentedAutofillLocked() {
         // Check if Smart Suggestions is supported...
         final @SmartSuggestionMode int supportedModes = mService
                 .getSupportedSmartSuggestionModesLocked();
         if (supportedModes == 0) return null;
 
         // ...then if the service is set for the user
-        final IntelligenceManagerInternal intelligenceManagerInternal = mService
-                .getMaster().mIntelligenceManagerInternal;
-        if (intelligenceManagerInternal == null) return null;
+
+        final RemoteAugmentedAutofillService remoteService = mService
+                .getRemoteAugmentedAutofillServiceLocked();
+        if (remoteService == null) return null;
 
         // Define which mode will be used
         final int mode;
@@ -2584,8 +2592,13 @@
         // TODO(b/111330312): we might need to add a new state in the AutofillManager to optimize
         // furgher AFM -> AFMS calls.
         // TODO(b/119638958): add CTS tests
-        return intelligenceManagerInternal.requestAutofill(mService.getUserId(), mClient,
-                mActivityToken, this.id, mCurrentViewId, currentValue);
+        remoteService.onRequestAutofillLocked(id, mClient, taskId, mComponentName, mCurrentViewId,
+                currentValue);
+
+        if (mAugmentedAutofillDestroyer == null) {
+            mAugmentedAutofillDestroyer = () -> remoteService.onDestroyAutofillWindowsRequest(id);
+        }
+        return mAugmentedAutofillDestroyer;
     }
 
     @GuardedBy("mLock")
@@ -2866,8 +2879,8 @@
         pw.print(prefix); pw.print("mSaveOnAllViewsInvisible: "); pw.println(
                 mSaveOnAllViewsInvisible);
         pw.print(prefix); pw.print("mSelectedDatasetIds: "); pw.println(mSelectedDatasetIds);
-        if (mAugmentedAutofillCallback != null) {
-            pw.print(prefix); pw.println("has AugmentedAutofillCallback");
+        if (mAugmentedAutofillDestroyer != null) {
+            pw.print(prefix); pw.println("has mAugmentedAutofillDestroyer");
         }
         mRemoteFillService.dump(prefix, pw);
     }
@@ -3045,8 +3058,9 @@
 
     @GuardedBy("mLock")
     void destroyAugmentedAutofillWindowsLocked() {
-        if (mAugmentedAutofillCallback != null) {
-            mAugmentedAutofillCallback.destroy();
+        if (mAugmentedAutofillDestroyer != null) {
+            mAugmentedAutofillDestroyer.run();
+            mAugmentedAutofillDestroyer = null;
         }
     }
 
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 0b06f28..3acdc8e3 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -27,7 +27,6 @@
 import android.app.job.JobScheduler;
 import android.app.job.JobService;
 import android.content.ComponentName;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -38,8 +37,6 @@
 import android.os.RemoteException;
 import android.os.Trace;
 import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -82,11 +79,11 @@
         return sInstance;
     }
 
-    /** Helper to create the {@link BackupManagerService} instance. */
-    public static BackupManagerService create(
-            Context context,
-            Trampoline parent,
-            HandlerThread backupThread) {
+    private UserBackupManagerService mUserBackupManagerService;
+
+    /** Instantiate a new instance of {@link BackupManagerService}. */
+    public BackupManagerService(
+            Context context, Trampoline trampoline, HandlerThread backupThread) {
         // Set up our transport options and initialize the default transport
         SystemConfig systemConfig = SystemConfig.getInstance();
         Set<ComponentName> transportWhitelist = systemConfig.getBackupTransportWhitelist();
@@ -94,50 +91,9 @@
             transportWhitelist = Collections.emptySet();
         }
 
-        String transport =
-                Settings.Secure.getString(
-                        context.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT);
-        if (TextUtils.isEmpty(transport)) {
-            transport = null;
-        }
-        if (DEBUG) {
-            Slog.v(TAG, "Starting with transport " + transport);
-        }
-        TransportManager transportManager =
-                new TransportManager(
-                        context,
-                        transportWhitelist,
-                        transport);
-
-        // If encrypted file systems is enabled or disabled, this call will return the
-        // correct directory.
-        File baseStateDir = new File(Environment.getDataDirectory(), "backup");
-
-        // This dir on /cache is managed directly in init.rc
-        File dataDir = new File(Environment.getDownloadCacheDirectory(), "backup_stage");
-
-        return new BackupManagerService(
-                context,
-                parent,
-                backupThread,
-                baseStateDir,
-                dataDir,
-                transportManager);
-    }
-
-    private UserBackupManagerService mUserBackupManagerService;
-
-    /** Instantiate a new instance of {@link BackupManagerService}. */
-    public BackupManagerService(
-            Context context,
-            Trampoline trampoline,
-            HandlerThread backupThread,
-            File baseStateDir,
-            File dataDir,
-            TransportManager transportManager) {
         mUserBackupManagerService =
-                new UserBackupManagerService(
-                        context, trampoline, backupThread, baseStateDir, dataDir, transportManager);
+                UserBackupManagerService.createAndInitializeService(
+                        context, trampoline, backupThread, transportWhitelist);
     }
 
     // TODO(b/118520567): Remove when tests are modified to use per-user instance.
@@ -151,30 +107,6 @@
      * a background thread to keep the unlock time down.
      */
     public void unlockSystemUser() {
-        // Migrate legacy setting
-        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup migrate");
-        if (!backupSettingMigrated(UserHandle.USER_SYSTEM)) {
-            if (DEBUG) {
-                Slog.i(TAG, "Backup enable apparently not migrated");
-            }
-            ContentResolver resolver = sInstance.getContext().getContentResolver();
-            int enableState = Settings.Secure.getIntForUser(resolver,
-                    Settings.Secure.BACKUP_ENABLED, -1, UserHandle.USER_SYSTEM);
-            if (enableState >= 0) {
-                if (DEBUG) {
-                    Slog.i(TAG, "Migrating enable state " + (enableState != 0));
-                }
-                writeBackupEnableState(enableState != 0, UserHandle.USER_SYSTEM);
-                Settings.Secure.putStringForUser(resolver,
-                        Settings.Secure.BACKUP_ENABLED, null, UserHandle.USER_SYSTEM);
-            } else {
-                if (DEBUG) {
-                    Slog.i(TAG, "Backup not yet configured; retaining null enable state");
-                }
-            }
-        }
-        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
         try {
             sInstance.setBackupEnabled(readBackupEnableState(UserHandle.USER_SYSTEM));
@@ -184,6 +116,15 @@
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
 
+    /**
+     * Starts the backup service for user {@code userId} by creating a new instance of {@link
+     * UserBackupManagerService} and registering it with this service.
+     */
+    // TODO(b/120212806): Add UserBackupManagerService initialization logic.
+    void startServiceForUser(int userId) {
+        // Intentionally empty.
+    }
+
     /*
      * The following methods are implementations of IBackupManager methods called from Trampoline.
      * They delegate to the appropriate per-user instance of UserBackupManagerService to perform the
@@ -563,12 +504,6 @@
         mUserBackupManagerService.dump(fd, pw, args);
     }
 
-    private static boolean backupSettingMigrated(int userId) {
-        File base = new File(Environment.getDataDirectory(), "backup");
-        File enableFile = new File(base, BACKUP_ENABLE_FILE);
-        return enableFile.exists();
-    }
-
     private static boolean readBackupEnableState(int userId) {
         File base = new File(Environment.getDataDirectory(), "backup");
         File enableFile = new File(base, BACKUP_ENABLE_FILE);
@@ -598,14 +533,8 @@
             stage.renameTo(enableFile);
             // will be synced immediately by the try-with-resources call to close()
         } catch (IOException | RuntimeException e) {
-            // Whoops; looks like we're doomed.  Roll everything out, disabled,
-            // including the legacy state.
             Slog.e(TAG, "Unable to record backup enable state; reverting to disabled: "
                     + e.getMessage());
-
-            ContentResolver resolver = sInstance.getContext().getContentResolver();
-            Settings.Secure.putStringForUser(resolver,
-                    Settings.Secure.BACKUP_ENABLED, null, userId);
             enableFile.delete();
             stage.delete();
         }
@@ -626,7 +555,9 @@
         @Override
         public void onUnlockUser(int userId) {
             if (userId == UserHandle.USER_SYSTEM) {
-                sInstance.unlockSystemUser();
+                sInstance.initializeServiceAndUnlockSystemUser();
+            } else {
+                sInstance.startServiceForUser(userId);
             }
         }
     }
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 59629aa..108f50d 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -41,6 +41,7 @@
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
@@ -81,6 +82,12 @@
     // Product-level suppression of backup/restore.
     private static final String BACKUP_DISABLE_PROPERTY = "ro.backup.disable";
 
+    private static final String BACKUP_THREAD = "backup";
+
+    /** Values for setting {@link Settings.Global#BACKUP_MULTI_USER_ENABLED} */
+    private static final int MULTI_USER_DISABLED = 0;
+    private static final int MULTI_USER_ENABLED = 1;
+
     private final Context mContext;
 
     @GuardedBy("mStateLock")
@@ -91,18 +98,31 @@
 
     private volatile BackupManagerService mService;
     private HandlerThread mHandlerThread;
+    private Handler mHandler;
 
     public Trampoline(Context context) {
         mContext = context;
         mGlobalDisable = isBackupDisabled();
         mSuppressFile = getSuppressFile();
         mSuppressFile.getParentFile().mkdirs();
+
+        mHandlerThread = new HandlerThread(BACKUP_THREAD, Process.THREAD_PRIORITY_BACKGROUND);
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
     }
 
     protected boolean isBackupDisabled() {
         return SystemProperties.getBoolean(BACKUP_DISABLE_PROPERTY, false);
     }
 
+    protected boolean isMultiUserEnabled() {
+        return Settings.Global.getInt(
+                mContext.getContentResolver(),
+                Settings.Global.BACKUP_MULTI_USER_ENABLED,
+                MULTI_USER_DISABLED)
+                == MULTI_USER_ENABLED;
+    }
+
     protected int binderGetCallingUid() {
         return Binder.getCallingUid();
     }
@@ -117,7 +137,7 @@
     }
 
     protected BackupManagerService createBackupManagerService() {
-        return BackupManagerService.create(mContext, this, mHandlerThread);
+        return new BackupManagerService(mContext, this, mHandlerThread);
     }
 
     /**
@@ -147,15 +167,9 @@
     /**
      * Called from {@link BackupManagerService.Lifecycle} when the system user is unlocked. Attempts
      * to initialize {@link BackupManagerService} and set backup state for the system user.
-     *
-     * @see BackupManagerService#unlockSystemUser()
      */
-    void unlockSystemUser() {
-        mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND);
-        mHandlerThread.start();
-
-        Handler h = new Handler(mHandlerThread.getLooper());
-        h.post(
+    void initializeServiceAndUnlockSystemUser() {
+        mHandler.post(
                 () -> {
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup init");
                     initializeService(UserHandle.USER_SYSTEM);
@@ -170,6 +184,29 @@
     }
 
     /**
+     * Called from {@link BackupManagerService.Lifecycle} when a non-system user {@code userId} is
+     * unlocked. Starts the backup service for this user if the service supports multi-user.
+     * Offloads work onto the handler thread {@link #mHandlerThread} to keep unlock time low.
+     */
+    // TODO(b/120212806): Consolidate service start for system and non-system users when system
+    // user-only logic is removed.
+    void startServiceForUser(int userId) {
+        if (!isMultiUserEnabled()) {
+            Slog.i(TAG, "Multi-user disabled, cannot start service for user: " + userId);
+            return;
+        }
+
+        mHandler.post(
+                () -> {
+                    BackupManagerService service = mService;
+                    if (service != null) {
+                        Slog.i(TAG, "Starting service for user: " + userId);
+                        service.startServiceForUser(userId);
+                    }
+                });
+    }
+
+    /**
      * Only privileged callers should be changing the backup state. This method only acts on {@link
      * UserHandle#USER_SYSTEM} and is a no-op if passed non-system users. Deactivating backup in the
      * system user also deactivates backup in all users.
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index fe16afe..5220a59 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
 
+import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.server.backup.BackupManagerService.DEBUG;
 import static com.android.server.backup.BackupManagerService.DEBUG_SCHEDULING;
 import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
@@ -68,6 +69,7 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -86,6 +88,7 @@
 import android.os.storage.IStorageManager;
 import android.os.storage.StorageManager;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.EventLog;
@@ -167,6 +170,10 @@
     // Persistently track the need to do a full init.
     private static final String INIT_SENTINEL_FILE_NAME = "_need_init_";
 
+    // Name of the directories the service stores bookkeeping data under.
+    private static final String BACKUP_PERSISTENT_DIR = "backup";
+    private static final String BACKUP_STAGING_DIR = "backup_stage";
+
     // System-private key used for backing up an app's widget state.  Must
     // begin with U+FFxx by convention (we reserve all keys starting
     // with U+FF00 or higher for system use).
@@ -360,15 +367,71 @@
     private long mAncestralToken = 0;
     private long mCurrentToken = 0;
 
+    /**
+     * Creates an instance of {@link UserBackupManagerService} and initializes state for it. This
+     * includes setting up the directories where we keep our bookkeeping and transport management.
+     *
+     * @see #createAndInitializeService(Context, Trampoline, HandlerThread, File, File,
+     *     TransportManager)
+     */
+    static UserBackupManagerService createAndInitializeService(
+            Context context,
+            Trampoline trampoline,
+            HandlerThread backupThread,
+            Set<ComponentName> transportWhitelist) {
+        String currentTransport =
+                Settings.Secure.getString(
+                        context.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT);
+        if (TextUtils.isEmpty(currentTransport)) {
+            currentTransport = null;
+        }
+
+        if (DEBUG) {
+            Slog.v(TAG, "Starting with transport " + currentTransport);
+        }
+        TransportManager transportManager =
+                new TransportManager(context, transportWhitelist, currentTransport);
+
+        File baseStateDir = new File(Environment.getDataDirectory(), BACKUP_PERSISTENT_DIR);
+
+        // This dir on /cache is managed directly in init.rc
+        File dataDir = new File(Environment.getDownloadCacheDirectory(), BACKUP_STAGING_DIR);
+
+        return createAndInitializeService(
+                context, trampoline, backupThread, baseStateDir, dataDir, transportManager);
+    }
+
+    /**
+     * Creates an instance of {@link UserBackupManagerService}.
+     *
+     * @param context The system server context.
+     * @param trampoline A reference to the proxy to {@link BackupManagerService}.
+     * @param backupThread The thread running backup/restore operations for the user.
+     * @param baseStateDir The directory we store the user's persistent bookkeeping data.
+     * @param dataDir The directory we store the user's temporary staging data.
+     * @param transportManager The {@link TransportManager} responsible for handling the user's
+     *     transports.
+     */
     @VisibleForTesting
-    public UserBackupManagerService(
+    public static UserBackupManagerService createAndInitializeService(
+            Context context,
+            Trampoline trampoline,
+            HandlerThread backupThread,
+            File baseStateDir,
+            File dataDir,
+            TransportManager transportManager) {
+        return new UserBackupManagerService(
+                context, trampoline, backupThread, baseStateDir, dataDir, transportManager);
+    }
+
+    private UserBackupManagerService(
             Context context,
             Trampoline parent,
             HandlerThread backupThread,
             File baseStateDir,
             File dataDir,
             TransportManager transportManager) {
-        mContext = context;
+        mContext = checkNotNull(context, "context cannot be null");
         mPackageManager = context.getPackageManager();
         mPackageManagerBinder = AppGlobals.getPackageManager();
         mActivityManager = ActivityManager.getService();
@@ -377,6 +440,7 @@
         mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
 
+        checkNotNull(parent, "trampoline cannot be null");
         mBackupManagerBinder = Trampoline.asInterface(parent.asBinder());
 
         mAgentTimeoutParameters = new
@@ -384,6 +448,7 @@
         mAgentTimeoutParameters.start();
 
         // spin up the backup/restore handler thread
+        checkNotNull(backupThread, "backupThread cannot be null");
         mBackupHandler = new BackupHandler(this, backupThread.getLooper());
 
         // Set up our bookkeeping
@@ -398,13 +463,13 @@
                 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
                 false, mProvisionedObserver);
 
-        mBaseStateDir = baseStateDir;
+        mBaseStateDir = checkNotNull(baseStateDir, "baseStateDir cannot be null");
         mBaseStateDir.mkdirs();
         if (!SELinux.restorecon(mBaseStateDir)) {
             Slog.e(TAG, "SELinux restorecon failed on " + mBaseStateDir);
         }
 
-        mDataDir = dataDir;
+        mDataDir = checkNotNull(dataDir, "dataDir cannot be null");
 
         mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng);
 
@@ -451,7 +516,7 @@
             addPackageParticipantsLocked(null);
         }
 
-        mTransportManager = transportManager;
+        mTransportManager = checkNotNull(transportManager, "transportManager cannot be null");
         mTransportManager.setOnTransportRegisteredListener(this::onTransportRegistered);
         mRegisterTransportsRequestedTime = SystemClock.elapsedRealtime();
         mBackupHandler.postDelayed(
@@ -465,7 +530,6 @@
         mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*");
     }
 
-
     public BackupManagerConstants getConstants() {
         return mConstants;
     }
diff --git a/services/intelligence/Android.bp b/services/contentcapture/Android.bp
similarity index 69%
rename from services/intelligence/Android.bp
rename to services/contentcapture/Android.bp
index 2df1235..57e859e 100644
--- a/services/intelligence/Android.bp
+++ b/services/contentcapture/Android.bp
@@ -1,5 +1,5 @@
 java_library_static {
-    name: "services.intelligence",
+    name: "services.contentcapture",
     srcs: ["java/**/*.java"],
     libs: ["services.core"],
 }
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
similarity index 68%
rename from services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index a760cbd..872fe42 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
 
-import static android.Manifest.permission.MANAGE_SMART_SUGGESTIONS;
+import static android.Manifest.permission.MANAGE_CONTENT_CAPTURE;
 import static android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE;
 
 import android.annotation.NonNull;
@@ -32,13 +32,9 @@
 import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.service.intelligence.InteractionSessionId;
 import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-import android.view.intelligence.IIntelligenceManager;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.IContentCaptureManager;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.IResultReceiver;
@@ -58,11 +54,10 @@
  * <p>The data collected by this service can be analyzed and combined with other sources to provide
  * contextual data in other areas of the system such as Autofill.
  */
-//TODO(b/111276913): rename once the final name is defined
-public final class IntelligenceManagerService extends
-        AbstractMasterSystemService<IntelligenceManagerService, IntelligencePerUserService> {
+public final class ContentCaptureManagerService extends
+        AbstractMasterSystemService<ContentCaptureManagerService, ContentCapturePerUserService> {
 
-    private static final String TAG = "IntelligenceManagerService";
+    private static final String TAG = ContentCaptureManagerService.class.getSimpleName();
 
     static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";
 
@@ -73,32 +68,32 @@
 
     private final LocalService mLocalService = new LocalService();
 
-    public IntelligenceManagerService(Context context) {
-        super(context, UserManager.DISALLOW_INTELLIGENCE_CAPTURE);
+    public ContentCaptureManagerService(Context context) {
+        super(context, UserManager.DISALLOW_CONTENT_CAPTURE);
     }
 
     @Override // from AbstractMasterSystemService
-    protected IntelligencePerUserService newServiceLocked(@UserIdInt int resolvedUserId,
+    protected ContentCapturePerUserService newServiceLocked(@UserIdInt int resolvedUserId,
             boolean disabled) {
-        return new IntelligencePerUserService(this, mLock, resolvedUserId);
+        return new ContentCapturePerUserService(this, mLock, resolvedUserId);
     }
 
     @Override // from SystemService
     public void onStart() {
         publishBinderService(CONTENT_CAPTURE_MANAGER_SERVICE,
-                new IntelligenceManagerServiceStub());
-        publishLocalService(IntelligenceManagerInternal.class, mLocalService);
+                new ContentCaptureManagerServiceStub());
+        publishLocalService(ContentCaptureManagerInternal.class, mLocalService);
     }
 
     @Override // from AbstractMasterSystemService
-    protected void onServiceRemoved(@NonNull IntelligencePerUserService service,
+    protected void onServiceRemoved(@NonNull ContentCapturePerUserService service,
             @UserIdInt int userId) {
         service.destroyLocked();
     }
 
     @Override // from AbstractMasterSystemService
     protected void enforceCallingPermissionForManagement() {
-        getContext().enforceCallingPermission(MANAGE_SMART_SUGGESTIONS, TAG);
+        getContext().enforceCallingPermission(MANAGE_CONTENT_CAPTURE, TAG);
     }
 
     @Override // from AbstractMasterSystemService
@@ -113,7 +108,7 @@
 
         synchronized (mLock) {
             if (userId != UserHandle.USER_ALL) {
-                final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+                final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     service.destroySessionsLocked();
                 }
@@ -139,7 +134,7 @@
 
         synchronized (mLock) {
             if (userId != UserHandle.USER_ALL) {
-                final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+                final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     service.listSessionsLocked(sessions);
                 }
@@ -165,11 +160,11 @@
         return mAm;
     }
 
-    final class IntelligenceManagerServiceStub extends IIntelligenceManager.Stub {
+    final class ContentCaptureManagerServiceStub extends IContentCaptureManager.Stub {
 
         @Override
         public void startSession(@UserIdInt int userId, @NonNull IBinder activityToken,
-                @NonNull ComponentName componentName, @NonNull InteractionSessionId sessionId,
+                @NonNull ComponentName componentName, @NonNull String sessionId,
                 int flags, @NonNull IResultReceiver result) {
             Preconditions.checkNotNull(activityToken);
             Preconditions.checkNotNull(componentName);
@@ -183,31 +178,31 @@
             final int displayId = 0;
 
             synchronized (mLock) {
-                final IntelligencePerUserService service = getServiceForUserLocked(userId);
+                final ContentCapturePerUserService service = getServiceForUserLocked(userId);
                 service.startSessionLocked(activityToken, componentName, taskId, displayId,
                         sessionId, flags, mAllowInstantService, result);
             }
         }
 
         @Override
-        public void sendEvents(@UserIdInt int userId, @NonNull InteractionSessionId sessionId,
+        public void sendEvents(@UserIdInt int userId, @NonNull String sessionId,
                 @NonNull List<ContentCaptureEvent> events) {
             Preconditions.checkNotNull(sessionId);
             Preconditions.checkNotNull(events);
 
             synchronized (mLock) {
-                final IntelligencePerUserService service = getServiceForUserLocked(userId);
+                final ContentCapturePerUserService service = getServiceForUserLocked(userId);
                 service.sendEventsLocked(sessionId, events);
             }
         }
 
         @Override
-        public void finishSession(@UserIdInt int userId, @NonNull InteractionSessionId sessionId,
+        public void finishSession(@UserIdInt int userId, @NonNull String sessionId,
                 @Nullable List<ContentCaptureEvent> events) {
             Preconditions.checkNotNull(sessionId);
 
             synchronized (mLock) {
-                final IntelligencePerUserService service = getServiceForUserLocked(userId);
+                final ContentCapturePerUserService service = getServiceForUserLocked(userId);
                 service.finishSessionLocked(sessionId, events);
             }
         }
@@ -225,19 +220,19 @@
         public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
                 String[] args, ShellCallback callback, ResultReceiver resultReceiver)
                 throws RemoteException {
-            new IntelligenceServiceShellCommand(IntelligenceManagerService.this).exec(
+            new ContentCaptureManagerServiceShellCommand(ContentCaptureManagerService.this).exec(
                     this, in, out, err, args, callback, resultReceiver);
         }
     }
 
-    private final class LocalService extends IntelligenceManagerInternal {
+    private final class LocalService extends ContentCaptureManagerInternal {
 
         @Override
-        public boolean isIntelligenceServiceForUser(int uid, @UserIdInt int userId) {
+        public boolean isContentCaptureServiceForUser(int uid, @UserIdInt int userId) {
             synchronized (mLock) {
-                final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+                final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
                 if (service != null) {
-                    return service.isIntelligenceServiceForUserLocked(uid);
+                    return service.isContentCaptureServiceForUserLocked(uid);
                 }
             }
             return false;
@@ -247,27 +242,12 @@
         public boolean sendActivityAssistData(@UserIdInt int userId, @NonNull IBinder activityToken,
                 @NonNull Bundle data) {
             synchronized (mLock) {
-                final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+                final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     return service.sendActivityAssistDataLocked(activityToken, data);
                 }
             }
             return false;
         }
-
-        @Override
-        public AugmentedAutofillCallback requestAutofill(@UserIdInt int userId,
-                @NonNull IAutoFillManagerClient client, @NonNull IBinder activityToken,
-                int autofillSessionId, @NonNull AutofillId focusedId,
-                @Nullable AutofillValue focusedValue) {
-            synchronized (mLock) {
-                final IntelligencePerUserService service = peekServiceForUserLocked(userId);
-                if (service != null) {
-                    return service.requestAutofill(client, activityToken, autofillSessionId,
-                            focusedId, focusedValue);
-                }
-            }
-            return null;
-        }
     }
 }
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
similarity index 89%
rename from services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
index 0d92a972..2f78276 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
@@ -13,9 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
 
-import static com.android.server.intelligence.IntelligenceManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS;
+import static com.android.server.contentcapture.ContentCaptureManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS;
 
 import android.annotation.NonNull;
 import android.os.Bundle;
@@ -30,14 +30,13 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * Shell Command implementation for {@link IntelligenceManagerService}.
+ * Shell Command implementation for {@link ContentCaptureManagerService}.
  */
-//TODO(b/111276913): rename once the final name is defined
-public final class IntelligenceServiceShellCommand extends ShellCommand {
+public final class ContentCaptureManagerServiceShellCommand extends ShellCommand {
 
-    private final IntelligenceManagerService mService;
+    private final ContentCaptureManagerService mService;
 
-    public IntelligenceServiceShellCommand(@NonNull IntelligenceManagerService service) {
+    public ContentCaptureManagerServiceShellCommand(@NonNull ContentCaptureManagerService service) {
         mService = service;
     }
 
@@ -64,8 +63,7 @@
     @Override
     public void onHelp() {
         try (PrintWriter pw = getOutPrintWriter();) {
-            // TODO(b/111276913): rename "intelligence" once SELinux rule changed
-            pw.println("Intelligence Service (intelligence) commands:");
+            pw.println("ContentCapture Service (content_capture) commands:");
             pw.println("  help");
             pw.println("    Prints this help text.");
             pw.println("");
@@ -106,7 +104,7 @@
             case "bind-instant-service-allowed":
                 return setBindInstantService(pw);
             case "temporary-service":
-                return setTemporaryService();
+                return setTemporaryService(pw);
             default:
                 pw.println("Invalid set: " + what);
                 return -1;
@@ -137,7 +135,7 @@
         }
     }
 
-    private int setTemporaryService() {
+    private int setTemporaryService(PrintWriter pw) {
         final int userId = getNextIntArgRequired();
         final String serviceName = getNextArg();
         if (serviceName == null) {
@@ -146,6 +144,8 @@
         }
         final int duration = getNextIntArgRequired();
         mService.setTemporaryService(userId, serviceName, duration);
+        pw.println("ContentCaptureService temporarily set to " + serviceName + " for "
+                + duration + "ms");
         return 0;
     }
 
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
similarity index 77%
rename from services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index e2b8d48..aa171f4 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
 
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
@@ -34,46 +34,40 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.SnapshotData;
+import android.service.contentcapture.SnapshotData;
 import android.util.ArrayMap;
 import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-import android.view.intelligence.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureManager;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.IResultReceiver;
 import com.android.server.infra.AbstractPerUserSystemService;
 import com.android.server.infra.FrameworkResourcesServiceNameResolver;
-import com.android.server.intelligence.IntelligenceManagerInternal.AugmentedAutofillCallback;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Per-user instance of {@link IntelligenceManagerService}.
+ * Per-user instance of {@link ContentCaptureManagerService}.
  */
-//TODO(b/111276913): rename once the final name is defined
-final class IntelligencePerUserService
-        extends AbstractPerUserSystemService<IntelligencePerUserService,
-            IntelligenceManagerService> {
+final class ContentCapturePerUserService
+        extends
+        AbstractPerUserSystemService<ContentCapturePerUserService, ContentCaptureManagerService> {
 
-    private static final String TAG = "IntelligencePerUserService";
+    private static final String TAG = ContentCaptureManagerService.class.getSimpleName();
 
     @GuardedBy("mLock")
-    private final ArrayMap<InteractionSessionId, ContentCaptureSession> mSessions =
+    private final ArrayMap<String, ContentCaptureSession> mSessions =
             new ArrayMap<>();
 
     // TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
 
-    protected IntelligencePerUserService(
-            IntelligenceManagerService master, Object lock, @UserIdInt int userId) {
+    protected ContentCapturePerUserService(
+            ContentCaptureManagerService master, Object lock, @UserIdInt int userId) {
         super(master, new FrameworkResourcesServiceNameResolver(master.getContext(), userId, lock,
-                com.android.internal.R.string.config_defaultSmartSuggestionsService), lock, userId);
+                com.android.internal.R.string.config_defaultContentCaptureService), lock, userId);
     }
 
     @Override // from PerUserSystemService
@@ -98,12 +92,12 @@
                     + " " + serviceComponent.flattenToShortString());
             return null;
         }
-        if (!Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE.equals(si.permission)) {
-            Slog.w(TAG, "SmartSuggestionsService from '" + si.packageName
+        if (!Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE.equals(si.permission)) {
+            Slog.w(TAG, "ContentCaptureService from '" + si.packageName
                     + "' does not require permission "
-                    + Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE);
+                    + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
             throw new SecurityException("Service does not require permission "
-                    + Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE);
+                    + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
         }
         return si;
     }
@@ -119,7 +113,7 @@
     @GuardedBy("mLock")
     public void startSessionLocked(@NonNull IBinder activityToken,
             @NonNull ComponentName componentName, int taskId, int displayId,
-            @NonNull InteractionSessionId sessionId, int flags, boolean bindInstantServiceAllowed,
+            @NonNull String sessionId, int flags, boolean bindInstantServiceAllowed,
             @NonNull IResultReceiver resultReceiver) {
         if (!isEnabledLocked()) {
             sendToClient(resultReceiver, ContentCaptureManager.STATE_DISABLED);
@@ -163,7 +157,7 @@
 
     // TODO(b/111276913): log metrics
     @GuardedBy("mLock")
-    public void finishSessionLocked(@NonNull InteractionSessionId sessionId,
+    public void finishSessionLocked(@NonNull String sessionId,
             @Nullable List<ContentCaptureEvent> events) {
         if (!isEnabledLocked()) {
             return;
@@ -180,7 +174,7 @@
             // TODO(b/111276913): for now we're sending the events and the onDestroy() in 2 separate
             // calls because it's not clear yet whether we'll change the manager to send events
             // to the service directly (i.e., without passing through system server). Once we
-            // decide, we might need to split IIntelligenceService.onSessionLifecycle() in 2
+            // decide, we might need to split IContentCaptureManager.onSessionLifecycle() in 2
             // methods, one for start and another for finish (and passing the events to finish),
             // otherwise the service might receive the 2 calls out of order.
             session.sendEventsLocked(events);
@@ -193,9 +187,9 @@
     }
 
     // TODO(b/111276913): need to figure out why some events are sent before session is started;
-    // probably because IntelligenceManager is not buffering them until it gets the session back
+    // probably because ContentCaptureManager is not buffering them until it gets the session back
     @GuardedBy("mLock")
-    public void sendEventsLocked(@NonNull InteractionSessionId sessionId,
+    public void sendEventsLocked(@NonNull String sessionId,
             @NonNull List<ContentCaptureEvent> events) {
         if (!isEnabledLocked()) {
             return;
@@ -216,7 +210,7 @@
     @GuardedBy("mLock")
     public boolean sendActivityAssistDataLocked(@NonNull IBinder activityToken,
             @NonNull Bundle data) {
-        final InteractionSessionId id = getInteractionSessionId(activityToken);
+        final String id = getSessionId(activityToken);
         if (id != null) {
             final ContentCaptureSession session = mSessions.get(id);
             final Bundle assistData = data.getBundle(ASSIST_KEY_DATA);
@@ -233,12 +227,12 @@
     }
 
     @GuardedBy("mLock")
-    public void removeSessionLocked(@NonNull InteractionSessionId sessionId) {
+    public void removeSessionLocked(@NonNull String sessionId) {
         mSessions.remove(sessionId);
     }
 
     @GuardedBy("mLock")
-    public boolean isIntelligenceServiceForUserLocked(int uid) {
+    public boolean isContentCaptureServiceForUserLocked(int uid) {
         return uid == getServiceUidLocked();
     }
 
@@ -283,24 +277,6 @@
         }
     }
 
-    public AugmentedAutofillCallback requestAutofill(@NonNull IAutoFillManagerClient client,
-            @NonNull IBinder activityToken, int autofillSessionId, @NonNull AutofillId focusedId,
-            @Nullable AutofillValue focusedValue) {
-        synchronized (mLock) {
-            final ContentCaptureSession session = getSession(activityToken);
-            if (session != null) {
-                // TODO(b/111330312): log metrics
-                if (mMaster.verbose) Slog.v(TAG, "requestAugmentedAutofill()");
-                return session.requestAutofillLocked(client, autofillSessionId, focusedId,
-                        focusedValue);
-            }
-            if (mMaster.debug) {
-                Slog.d(TAG, "requestAutofill(): no session for " + activityToken);
-            }
-            return null;
-        }
-    }
-
     @Override
     protected void dumpLocked(String prefix, PrintWriter pw) {
         super.dumpLocked(prefix, pw);
@@ -319,10 +295,10 @@
     }
 
     /**
-     * Returns the InteractionSessionId associated with the given activity.
+     * Returns the session id associated with the given activity.
      */
     @GuardedBy("mLock")
-    private InteractionSessionId getInteractionSessionId(@NonNull IBinder activityToken) {
+    private String getSessionId(@NonNull IBinder activityToken) {
         for (int i = 0; i < mSessions.size(); i++) {
             ContentCaptureSession session = mSessions.valueAt(i);
             if (session.isActivitySession(activityToken)) {
diff --git a/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureSession.java
similarity index 63%
rename from services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCaptureSession.java
index 05b8201..2302b7d 100644
--- a/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureSession.java
@@ -13,55 +13,49 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.IBinder;
-import android.service.intelligence.InteractionContext;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.SmartSuggestionsService;
-import android.service.intelligence.SnapshotData;
+import android.service.contentcapture.ContentCaptureService;
+import android.service.contentcapture.InteractionContext;
+import android.service.contentcapture.InteractionSessionId;
+import android.service.contentcapture.SnapshotData;
 import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureEvent;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
+import com.android.server.contentcapture.RemoteContentCaptureService.ContentCaptureServiceCallbacks;
 import com.android.server.infra.AbstractRemoteService;
-import com.android.server.intelligence.IntelligenceManagerInternal.AugmentedAutofillCallback;
-import com.android.server.intelligence.RemoteIntelligenceService.RemoteIntelligenceServiceCallbacks;
 
 import java.io.PrintWriter;
 import java.util.List;
 
-final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks {
+final class ContentCaptureSession implements ContentCaptureServiceCallbacks {
 
     private static final String TAG = "ContentCaptureSession";
 
     private final Object mLock;
     final IBinder mActivityToken;
-    private final IntelligencePerUserService mService;
-    private final RemoteIntelligenceService mRemoteService;
+    private final ContentCapturePerUserService mService;
+    private final RemoteContentCaptureService mRemoteService;
     private final InteractionContext mInterationContext;
-    private final InteractionSessionId mId;
-    private AugmentedAutofillCallback mAutofillCallback;
+    private final String mId;
 
     ContentCaptureSession(@NonNull Context context, int userId, @NonNull Object lock,
-            @NonNull IBinder activityToken, @NonNull IntelligencePerUserService service,
+            @NonNull IBinder activityToken, @NonNull ContentCapturePerUserService service,
             @NonNull ComponentName serviceComponentName, @NonNull ComponentName appComponentName,
-            int taskId, int displayId, @NonNull InteractionSessionId sessionId, int flags,
+            int taskId, int displayId, @NonNull String sessionId, int flags,
             boolean bindInstantServiceAllowed, boolean verbose) {
         mLock = lock;
         mActivityToken = activityToken;
         mService = service;
         mId = Preconditions.checkNotNull(sessionId);
-        mRemoteService = new RemoteIntelligenceService(context,
-                SmartSuggestionsService.SERVICE_INTERFACE, serviceComponentName, userId, this,
+        mRemoteService = new RemoteContentCaptureService(context,
+                ContentCaptureService.SERVICE_INTERFACE, serviceComponentName, userId, this,
                 bindInstantServiceAllowed, verbose);
         mInterationContext = new InteractionContext(appComponentName, taskId, displayId, flags);
     }
@@ -74,7 +68,7 @@
     }
 
     /**
-     * Notifies the {@link SmartSuggestionsService} that the service started.
+     * Notifies the {@link ContentCaptureService} that the service started.
      */
     @GuardedBy("mLock")
     public void notifySessionStartedLocked() {
@@ -82,14 +76,14 @@
     }
 
     /**
-     * Notifies the {@link SmartSuggestionsService} of a batch of events.
+     * Notifies the {@link ContentCaptureService} of a batch of events.
      */
     public void sendEventsLocked(@NonNull List<ContentCaptureEvent> events) {
         mRemoteService.onContentCaptureEventsRequest(mId, events);
     }
 
     /**
-     * Notifies the {@link SmartSuggestionsService} of a snapshot of an activity.
+     * Notifies the {@link ContentCaptureService} of a snapshot of an activity.
      */
     @GuardedBy("mLock")
     public void sendActivitySnapshotLocked(@NonNull SnapshotData snapshotData) {
@@ -97,24 +91,10 @@
     }
 
     /**
-     * Requests the service to autofill the given field.
-     */
-    public AugmentedAutofillCallback requestAutofillLocked(@NonNull IAutoFillManagerClient client,
-            int autofillSessionId, @NonNull AutofillId focusedId,
-            @Nullable AutofillValue focusedValue) {
-        mRemoteService.onRequestAutofillLocked(mId, client, autofillSessionId, focusedId,
-                focusedValue);
-        if (mAutofillCallback == null) {
-            mAutofillCallback = () -> mRemoteService.onDestroyAutofillWindowsRequest(mId);
-        }
-        return mAutofillCallback;
-    }
-
-    /**
      * Cleans up the session and removes it from the service.
      *
      * @param notifyRemoteService whether it should trigger a {@link
-     * SmartSuggestionsService#onDestroyInteractionSession(InteractionSessionId)}
+     * ContentCaptureService#onDestroyInteractionSession(InteractionSessionId)}
      * request.
      */
     @GuardedBy("mLock")
@@ -130,7 +110,7 @@
      * Cleans up the session, but not removes it from the service.
      *
      * @param notifyRemoteService whether it should trigger a {@link
-     * SmartSuggestionsService#onDestroyInteractionSession(InteractionSessionId)}
+     * ContentCaptureService#onDestroyInteractionSession(InteractionSessionId)}
      * request.
      */
     @GuardedBy("mLock")
@@ -138,11 +118,6 @@
         if (mService.isVerbose()) {
             Slog.v(TAG, "destroyLocked(notifyRemoteService=" + notifyRemoteService + ")");
         }
-        if (mAutofillCallback != null) {
-            mAutofillCallback.destroy();
-            mAutofillCallback = null;
-        }
-
         // TODO(b/111276913): must call client to set session as FINISHED_BY_SERVER
         if (notifyRemoteService) {
             mRemoteService.onSessionLifecycleRequest(/* context= */ null, mId);
@@ -173,19 +148,18 @@
 
     @GuardedBy("mLock")
     public void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
-        pw.print(prefix); pw.print("id: ");  mId.dump(pw); pw.println();
+        pw.print(prefix); pw.print("id: ");  pw.print(mId); pw.println();
         pw.print(prefix); pw.print("context: ");  mInterationContext.dump(pw); pw.println();
         pw.print(prefix); pw.print("activity token: "); pw.println(mActivityToken);
         pw.print(prefix); pw.print("has autofill callback: ");
-        pw.println(mAutofillCallback != null);
     }
 
     String toShortString() {
-        return mId.getValue() + ":" + mActivityToken;
+        return mId  + ":" + mActivityToken;
     }
 
     @Override
     public String toString() {
-        return "ContentCaptureSession[id=" + mId.getValue() + ", act=" + mActivityToken + "]";
+        return "ContentCaptureSession[id=" + mId + ", act=" + mActivityToken + "]";
     }
 }
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
new file mode 100644
index 0000000..6a111f2
--- /dev/null
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -0,0 +1,201 @@
+/*
+ * 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.server.contentcapture;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.service.contentcapture.ContentCaptureEventsRequest;
+import android.service.contentcapture.IContentCaptureService;
+import android.service.contentcapture.InteractionContext;
+import android.service.contentcapture.SnapshotData;
+import android.text.format.DateUtils;
+import android.util.Slog;
+import android.view.contentcapture.ContentCaptureEvent;
+
+import com.android.server.infra.AbstractMultiplePendingRequestsRemoteService;
+
+import java.util.List;
+
+final class RemoteContentCaptureService
+        extends AbstractMultiplePendingRequestsRemoteService<RemoteContentCaptureService> {
+
+    private static final String TAG = RemoteContentCaptureService.class.getSimpleName();
+
+    // TODO(b/117779333): changed it so it's permanentely bound
+    private static final long TIMEOUT_IDLE_BIND_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
+    private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
+
+    private final ContentCaptureServiceCallbacks mCallbacks;
+    private IContentCaptureService mService;
+
+    RemoteContentCaptureService(Context context, String serviceInterface,
+            ComponentName componentName, int userId,
+            ContentCaptureServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
+            boolean verbose) {
+        super(context, serviceInterface, componentName, userId, callbacks,
+                bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2);
+        mCallbacks = callbacks;
+    }
+
+    @Override // from RemoteService
+    protected IInterface getServiceInterface(@NonNull IBinder service) {
+        mService = IContentCaptureService.Stub.asInterface(service);
+        return mService;
+    }
+
+    // TODO(b/111276913): modify super class to allow permanent binding when value is 0 or negative
+    @Override // from RemoteService
+    protected long getTimeoutIdleBindMillis() {
+        // TODO(b/111276913): read from Settings so it can be changed in the field
+        return TIMEOUT_IDLE_BIND_MILLIS;
+    }
+
+    @Override // from RemoteService
+    protected long getRemoteRequestMillis() {
+        // TODO(b/111276913): read from Settings so it can be changed in the field
+        return TIMEOUT_REMOTE_REQUEST_MILLIS;
+    }
+
+    /**
+     * Called by {@link ContentCaptureSession} to generate a call to the
+     * {@link RemoteContentCaptureService} to indicate the session was created (when {@code context}
+     * is not {@code null} or destroyed (when {@code context} is {@code null}).
+     */
+    public void onSessionLifecycleRequest(@Nullable InteractionContext context,
+            @NonNull String sessionId) {
+        cancelScheduledUnbind();
+        scheduleRequest(new PendingSessionLifecycleRequest(this, context, sessionId));
+    }
+
+    /**
+     * Called by {@link ContentCaptureSession} to send a batch of events to the service.
+     */
+    public void onContentCaptureEventsRequest(@NonNull String sessionId,
+            @NonNull List<ContentCaptureEvent> events) {
+        cancelScheduledUnbind();
+        scheduleRequest(new PendingOnContentCaptureEventsRequest(this, sessionId, events));
+    }
+
+    /**
+     * Called by {@link ContentCaptureSession} to send snapshot data to the service.
+     */
+    public void onActivitySnapshotRequest(@NonNull String sessionId,
+            @NonNull SnapshotData snapshotData) {
+        cancelScheduledUnbind();
+        scheduleRequest(new PendingOnActivitySnapshotRequest(this, sessionId, snapshotData));
+    }
+
+    private abstract static class MyPendingRequest
+            extends PendingRequest<RemoteContentCaptureService> {
+        protected final String mSessionId;
+
+        private MyPendingRequest(@NonNull RemoteContentCaptureService service,
+                @NonNull String sessionId) {
+            super(service);
+            mSessionId = sessionId;
+        }
+
+        @Override // from PendingRequest
+        protected final void onTimeout(RemoteContentCaptureService remoteService) {
+            Slog.w(TAG, "timed out handling " + getClass().getSimpleName() + " for "
+                    + mSessionId);
+            remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ true);
+        }
+
+        @Override // from PendingRequest
+        public final void run() {
+            final RemoteContentCaptureService remoteService = getService();
+            if (remoteService != null) {
+                try {
+                    // We don't expect the service to call us back, so we finish right away.
+                    myRun(remoteService);
+                    // TODO(b/111330312): not true anymore!!
+                    finish();
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "exception handling " + getClass().getSimpleName() + " for "
+                            + mSessionId + ": " + e);
+                    remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ false);
+                }
+            }
+        }
+
+        protected abstract void myRun(@NonNull RemoteContentCaptureService service)
+                throws RemoteException;
+
+    }
+
+    private static final class PendingSessionLifecycleRequest extends MyPendingRequest {
+
+        private final InteractionContext mContext;
+
+        protected PendingSessionLifecycleRequest(@NonNull RemoteContentCaptureService service,
+                @Nullable InteractionContext context, @NonNull String sessionId) {
+            super(service, sessionId);
+            mContext = context;
+        }
+
+        @Override // from MyPendingRequest
+        public void myRun(@NonNull RemoteContentCaptureService remoteService)
+                throws RemoteException {
+            remoteService.mService.onSessionLifecycle(mContext, mSessionId);
+        }
+    }
+
+    private static final class PendingOnContentCaptureEventsRequest extends MyPendingRequest {
+
+        private final List<ContentCaptureEvent> mEvents;
+
+        protected PendingOnContentCaptureEventsRequest(@NonNull RemoteContentCaptureService service,
+                @NonNull String sessionId, @NonNull List<ContentCaptureEvent> events) {
+            super(service, sessionId);
+            mEvents = events;
+        }
+
+        @Override // from MyPendingRequest
+        public void myRun(@NonNull RemoteContentCaptureService remoteService)
+                throws RemoteException {
+            remoteService.mService.onContentCaptureEventsRequest(mSessionId,
+                    new ContentCaptureEventsRequest(mEvents));
+        }
+    }
+
+    private static final class PendingOnActivitySnapshotRequest extends MyPendingRequest {
+
+        private final SnapshotData mSnapshotData;
+
+        protected PendingOnActivitySnapshotRequest(@NonNull RemoteContentCaptureService service,
+                @NonNull String sessionId, @NonNull SnapshotData snapshotData) {
+            super(service, sessionId);
+            mSnapshotData = snapshotData;
+        }
+
+        @Override // from MyPendingRequest
+        protected void myRun(@NonNull RemoteContentCaptureService remoteService)
+                throws RemoteException {
+            remoteService.mService.onActivitySnapshot(mSessionId, mSnapshotData);
+        }
+    }
+
+    public interface ContentCaptureServiceCallbacks extends VultureCallback {
+        // To keep it simple, we use the same callback for all failures / timeouts.
+        void onFailureOrTimeout(boolean timedOut);
+    }
+}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 784d398..cccacf4 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -15,14 +15,13 @@
         "java/**/*.java",
         ":dumpstate_aidl",
         ":idmap2_aidl",
-        ":netd_aidl",
-        ":netd_metrics_aidl",
         ":installd_aidl",
         ":storaged_aidl",
         ":vold_aidl",
         ":mediaupdateservice_aidl",
         "java/com/android/server/EventLogTags.logtags",
         "java/com/android/server/am/EventLogTags.logtags",
+        ":netd_metrics_aidl",
     ],
 
     libs: [
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index dbea529..4b092b2 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2526,6 +2526,19 @@
         }
     }
 
+    /**
+     * Signal that checkpointing partitions should commit changes
+     */
+    @Override
+    public void commitChanges() throws RemoteException {
+        // Only the system process is permitted to commit checkpoints
+        if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
+            throw new SecurityException("no permission to commit checkpoint changes");
+        }
+
+        mVold.commitChanges();
+    }
+
     @Override
     public String getPassword() throws RemoteException {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c16f1db..40da881 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1199,8 +1199,8 @@
         void setProfileProc(ProcessRecord profileProc) {
             mProfileProc = profileProc;
             if (mAtmInternal != null) {
-                mAtmInternal.setProfileProc(
-                        profileProc.getWindowProcessController());
+                mAtmInternal.setProfileProc(profileProc == null ? null
+                        : profileProc.getWindowProcessController());
             }
         }
 
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 9cfd39c..65cd329 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -55,7 +55,12 @@
         // add other system settings here...
 
         sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.class);
-        sGlobalSettingToTypeMap.put(Settings.Global.ANGLE_ENABLED_APP, String.class);
+        sGlobalSettingToTypeMap.put(
+                Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE, String.class);
+        sGlobalSettingToTypeMap.put(
+                Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS, String.class);
+        sGlobalSettingToTypeMap.put(
+                Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES, String.class);
         sGlobalSettingToTypeMap.put(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, int.class);
         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_APP, String.class);
         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS, String.class);
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 271b37e..bcce052 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -67,6 +67,7 @@
 import android.os.IUserManager;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -332,6 +333,14 @@
                 return;
             }
         }
+        // Inform checkpointing systems of success
+        try {
+            getStorageManager().commitChanges();
+        } catch (Exception e) {
+            PowerManager pm = (PowerManager)
+                     mInjector.getContext().getSystemService(Context.POWER_SERVICE);
+            pm.reboot("Checkpoint commit failed");
+        }
 
         // We always walk through all the user lifecycle states to send
         // consistent developer events. We step into RUNNING_LOCKED here,
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index add55ea..1882be2 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -813,6 +813,24 @@
             }
         }
 
+        @Override // Binder call
+        public void resetTimeout(byte[] token) {
+            checkInternalPermission();
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                if (mFingerprintService != null) {
+                    mFingerprintService.resetTimeout(token);
+                }
+                if (mFaceService != null) {
+                    mFaceService.resetTimeout(token);
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception", e);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
         void cancelInternal(IBinder token, String opPackageName, boolean fromClient) {
             final int callingUid = Binder.getCallingUid();
             final int callingPid = Binder.getCallingPid();
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 65537ad..258c325 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -55,7 +55,7 @@
 
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
-import com.android.server.intelligence.IntelligenceManagerInternal;
+import com.android.server.contentcapture.ContentCaptureManagerInternal;
 import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -158,7 +158,7 @@
     private final IUserManager mUm;
     private final PackageManager mPm;
     private final AppOpsManager mAppOps;
-    private final IntelligenceManagerInternal mIm;
+    private final ContentCaptureManagerInternal mContentCaptureInternal;
     private final IBinder mPermissionOwner;
     private HostClipboardMonitor mHostClipboardMonitor = null;
     private Thread mHostMonitorThread = null;
@@ -178,7 +178,7 @@
         mPm = getContext().getPackageManager();
         mUm = (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
-        mIm = LocalServices.getService(IntelligenceManagerInternal.class);
+        mContentCaptureInternal = LocalServices.getService(ContentCaptureManagerInternal.class);
         final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard");
         mPermissionOwner = permOwner;
         if (IS_EMULATOR) {
@@ -652,9 +652,10 @@
             case AppOpsManager.OP_READ_CLIPBOARD:
                 // Clipboard can only be read by applications with focus..
                 boolean allowed = mWm.isUidFocused(callingUid);
-                if (!allowed && mIm != null) {
+                if (!allowed && mContentCaptureInternal != null) {
                     // ...or the Intelligence Service
-                    allowed = mIm.isIntelligenceServiceForUser(callingUid, userId);
+                    allowed = mContentCaptureInternal.isContentCaptureServiceForUser(callingUid,
+                            userId);
                 }
                 if (!allowed) {
                     Slog.e(TAG, "Denying clipboard access to " + callingPackage
diff --git a/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java b/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java
new file mode 100644
index 0000000..726362a
--- /dev/null
+++ b/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java
@@ -0,0 +1,44 @@
+/*
+ * 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.server.contentcapture;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.os.Bundle;
+import android.os.IBinder;
+
+/**
+ * ContentCapture Manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class ContentCaptureManagerInternal {
+
+    /**
+     * Checks whether the given {@code uid} owns the
+     * {@link android.service.contentcapture.ContentCaptureService} implementation associated with
+     * the given {@code userId}.
+     */
+    public abstract boolean isContentCaptureServiceForUser(int uid, @UserIdInt int userId);
+
+    /**
+     * Notifies the intelligence service of new assist data for the given activity.
+     *
+     * @return {@code false} if there was no service set for the given user
+     */
+    public abstract boolean sendActivityAssistData(@UserIdInt int userId,
+            @NonNull IBinder activityToken, @NonNull Bundle data);
+}
diff --git a/services/core/java/com/android/server/display/DisplayTransformManager.java b/services/core/java/com/android/server/display/DisplayTransformManager.java
index 5ca1755..4ad26da 100644
--- a/services/core/java/com/android/server/display/DisplayTransformManager.java
+++ b/services/core/java/com/android/server/display/DisplayTransformManager.java
@@ -23,7 +23,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
-import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
 
@@ -68,7 +67,7 @@
      * SurfaceFlinger display color (managed, unmanaged, etc.).
      */
     private static final int SURFACE_FLINGER_TRANSACTION_DISPLAY_COLOR = 1023;
-    private static final int SURFACE_FLINGER_TRANSACTION_QUERY_WIDE_COLOR = 1030;
+    private static final int SURFACE_FLINGER_TRANSACTION_QUERY_COLOR_MANAGED = 1030;
 
     private static final String PERSISTENT_PROPERTY_SATURATION = "persist.sys.sf.color_saturation";
     private static final String PERSISTENT_PROPERTY_DISPLAY_COLOR = "persist.sys.sf.native_mode";
@@ -270,8 +269,8 @@
     }
 
     /**
-     * Returns whether the screen is wide color gamut via SurfaceFlinger's
-     * {@link #SURFACE_FLINGER_TRANSACTION_QUERY_WIDE_COLOR}.
+     * Returns whether the screen is color managed via SurfaceFlinger's
+     * {@link #SURFACE_FLINGER_TRANSACTION_QUERY_COLOR_MANAGED}.
      */
     public boolean isDeviceColorManaged() {
         final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER);
@@ -280,10 +279,10 @@
             final Parcel reply = Parcel.obtain();
             data.writeInterfaceToken("android.ui.ISurfaceComposer");
             try {
-                flinger.transact(SURFACE_FLINGER_TRANSACTION_QUERY_WIDE_COLOR, data, reply, 0);
+                flinger.transact(SURFACE_FLINGER_TRANSACTION_QUERY_COLOR_MANAGED, data, reply, 0);
                 return reply.readBoolean();
             } catch (RemoteException ex) {
-                Log.e(TAG, "Failed to query wide color support", ex);
+                Slog.e(TAG, "Failed to query wide color support", ex);
             } finally {
                 data.recycle();
                 reply.recycle();
@@ -305,7 +304,7 @@
             try {
                 flinger.transact(SURFACE_FLINGER_TRANSACTION_SATURATION, data, null, 0);
             } catch (RemoteException ex) {
-                Log.e(TAG, "Failed to set saturation", ex);
+                Slog.e(TAG, "Failed to set saturation", ex);
             } finally {
                 data.recycle();
             }
@@ -325,7 +324,7 @@
             try {
                 flinger.transact(SURFACE_FLINGER_TRANSACTION_DISPLAY_COLOR, data, null, 0);
             } catch (RemoteException ex) {
-                Log.e(TAG, "Failed to set display color", ex);
+                Slog.e(TAG, "Failed to set display color", ex);
             } finally {
                 data.recycle();
             }
@@ -336,7 +335,7 @@
         try {
             ActivityTaskManager.getService().updateConfiguration(null);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not update configuration", e);
+            Slog.e(TAG, "Could not update configuration", e);
         }
     }
 }
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index ef9ad8a..c0c4a6e 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -58,7 +58,7 @@
  * <ul>
  *   <li>Disabling the service when {@link UserManager} restrictions change.
  *   <li>Refreshing the service when its underlying
- *   {@link #getSettingsProperty() Settings property} changed.
+ *   {@link #getServiceSettingsProperty() Settings property} changed.
  *   <li>Calling the service when other Settings properties changed.
  * </ul>
  *
diff --git a/services/core/java/com/android/server/infra/AbstractRemoteService.java b/services/core/java/com/android/server/infra/AbstractRemoteService.java
index 7af1d4c..67b3ecf 100644
--- a/services/core/java/com/android/server/infra/AbstractRemoteService.java
+++ b/services/core/java/com/android/server/infra/AbstractRemoteService.java
@@ -248,7 +248,7 @@
         if (checkIfDestroyed() || mCompleted) return;
 
         if (!handleIsBound()) {
-            if (mVerbose) Slog.v(mTag, "handlePendingRequest(): queuing" + pendingRequest);
+            if (mVerbose) Slog.v(mTag, "handlePendingRequest(): queuing " + pendingRequest);
             handlePendingRequestWhileUnBound(pendingRequest);
             handleEnsureBound();
         } else {
@@ -379,6 +379,7 @@
 
                 final S remoteService = mWeakService.get();
                 if (remoteService != null) {
+                    // TODO(b/117779333): we should probably ignore it if service is destroyed.
                     Slog.w(mTag, "timed out after " + service.getRemoteRequestMillis() + " ms");
                     onTimeout(remoteService);
                 } else {
diff --git a/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java b/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java
index 8f8b448..37a1f54 100644
--- a/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java
+++ b/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java
@@ -73,7 +73,8 @@
     void handlePendingRequestWhileUnBound(@NonNull PendingRequest<S> pendingRequest) {
         if (mPendingRequest != null) {
             if (mVerbose) {
-                Slog.v(mTag, "handlePendingRequestWhileUnBound(): cancelling " + mPendingRequest);
+                Slog.v(mTag, "handlePendingRequestWhileUnBound(): cancelling " + mPendingRequest
+                        + " to handle " + pendingRequest);
             }
             mPendingRequest.cancel();
         }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index a8da968..7717a57 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1617,7 +1617,8 @@
     // Check whether or not this is a valid IPC. Assumes an IPC is valid when either
     // 1) it comes from the system process
     // 2) the calling process' user id is identical to the current user id IMMS thinks.
-    private boolean calledFromValidUser() {
+    @GuardedBy("mMethodMap")
+    private boolean calledFromValidUserLocked() {
         final int uid = Binder.getCallingUid();
         final int userId = UserHandle.getUserId(uid);
         if (DEBUG) {
@@ -1657,7 +1658,8 @@
      * @param token The window token given to the input method when it was started.
      * @return true if and only if non-null valid token is specified.
      */
-    private boolean calledWithValidToken(@Nullable IBinder token) {
+    @GuardedBy("mMethodMap")
+    private boolean calledWithValidTokenLocked(@Nullable IBinder token) {
         if (token == null && Binder.getCallingPid() == Process.myPid()) {
             if (DEBUG) {
                 // TODO(b/34851776): Basically it's the caller's fault if we reach here.
@@ -1698,11 +1700,11 @@
     }
 
     private List<InputMethodInfo> getInputMethodList(final boolean isVrOnly) {
-        // TODO: Make this work even for non-current users?
-        if (!calledFromValidUser()) {
-            return Collections.emptyList();
-        }
         synchronized (mMethodMap) {
+            // TODO: Make this work even for non-current users?
+            if (!calledFromValidUserLocked()) {
+                return Collections.emptyList();
+            }
             ArrayList<InputMethodInfo> methodList = new ArrayList<>();
             for (InputMethodInfo info : mMethodList) {
 
@@ -1716,11 +1718,11 @@
 
     @Override
     public List<InputMethodInfo> getEnabledInputMethodList() {
-        // TODO: Make this work even for non-current users?
-        if (!calledFromValidUser()) {
-            return Collections.emptyList();
-        }
         synchronized (mMethodMap) {
+            // TODO: Make this work even for non-current users?
+            if (!calledFromValidUserLocked()) {
+                return Collections.emptyList();
+            }
             return mSettings.getEnabledInputMethodListLocked();
         }
     }
@@ -1732,11 +1734,11 @@
     @Override
     public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
             boolean allowsImplicitlySelectedSubtypes) {
-        // TODO: Make this work even for non-current users?
-        if (!calledFromValidUser()) {
-            return Collections.emptyList();
-        }
         synchronized (mMethodMap) {
+            // TODO: Make this work even for non-current users?
+            if (!calledFromValidUserLocked()) {
+                return Collections.emptyList();
+            }
             final InputMethodInfo imi;
             if (imiId == null && mCurMethodId != null) {
                 imi = mMethodMap.get(mCurMethodId);
@@ -2238,7 +2240,7 @@
     private void updateStatusIcon(@NonNull IBinder token, String packageName,
             @DrawableRes int iconId) {
         synchronized (mMethodMap) {
-            if (!calledWithValidToken(token)) {
+            if (!calledWithValidTokenLocked(token)) {
                 return;
             }
             final long ident = Binder.clearCallingIdentity();
@@ -2341,11 +2343,10 @@
     @BinderThread
     @SuppressWarnings("deprecation")
     private void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
-        if (!calledWithValidToken(token)) {
-            return;
-        }
-
         synchronized (mMethodMap) {
+            if (!calledWithValidTokenLocked(token)) {
+                return;
+            }
             mImeWindowVis = vis;
             mBackDisposition = backDisposition;
             updateSystemUiLocked(token, vis, backDisposition);
@@ -2376,11 +2377,10 @@
 
     @BinderThread
     private void reportStartInput(IBinder token, IBinder startInputToken) {
-        if (!calledWithValidToken(token)) {
-            return;
-        }
-
         synchronized (mMethodMap) {
+            if (!calledWithValidTokenLocked(token)) {
+                return;
+            }
             final IBinder targetWindow = mImeTargetWindowMap.get(startInputToken);
             if (targetWindow != null && mLastImeTargetWindow != targetWindow) {
                 mWindowManagerInternal.updateInputMethodTargetWindow(token, targetWindow);
@@ -2391,7 +2391,7 @@
 
     // Caution! This method is called in this class. Handle multi-user carefully
     private void updateSystemUiLocked(IBinder token, int vis, int backDisposition) {
-        if (!calledWithValidToken(token)) {
+        if (!calledWithValidTokenLocked(token)) {
             return;
         }
 
@@ -2450,10 +2450,10 @@
 
     @Override
     public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
-        if (!calledFromValidUser()) {
-            return;
-        }
         synchronized (mMethodMap) {
+            if (!calledFromValidUserLocked()) {
+                return;
+            }
             final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
             for (int i = 0; i < spans.length; ++i) {
                 SuggestionSpan ss = spans[i];
@@ -2466,10 +2466,10 @@
 
     @Override
     public boolean notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
-        if (!calledFromValidUser()) {
-            return false;
-        }
         synchronized (mMethodMap) {
+            if (!calledFromValidUserLocked()) {
+                return false;
+            }
             final InputMethodInfo targetImi = mSecureSuggestionSpans.get(span);
             // TODO: Do not send the intent if the process of the targetImi is already dead.
             if (targetImi != null) {
@@ -2633,13 +2633,13 @@
     @Override
     public boolean showSoftInput(IInputMethodClient client, int flags,
             ResultReceiver resultReceiver) {
-        if (!calledFromValidUser()) {
-            return false;
-        }
         int uid = Binder.getCallingUid();
-        long ident = Binder.clearCallingIdentity();
-        try {
-            synchronized (mMethodMap) {
+        synchronized (mMethodMap) {
+            if (!calledFromValidUserLocked()) {
+                return false;
+            }
+            final long ident = Binder.clearCallingIdentity();
+            try {
                 if (mCurClient == null || client == null
                         || mCurClient.client.asBinder() != client.asBinder()) {
                     // We need to check if this is the current client with
@@ -2657,9 +2657,9 @@
                 }
                 if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
                 return showCurrentInputLocked(flags, resultReceiver);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
             }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -2718,13 +2718,13 @@
     @Override
     public boolean hideSoftInput(IInputMethodClient client, int flags,
             ResultReceiver resultReceiver) {
-        if (!calledFromValidUser()) {
-            return false;
-        }
         int uid = Binder.getCallingUid();
-        long ident = Binder.clearCallingIdentity();
-        try {
-            synchronized (mMethodMap) {
+        synchronized (mMethodMap) {
+            if (!calledFromValidUserLocked()) {
+                return false;
+            }
+            final long ident = Binder.clearCallingIdentity();
+            try {
                 if (mCurClient == null || client == null
                         || mCurClient.client.asBinder() != client.asBinder()) {
                     // We need to check if this is the current client with
@@ -2745,9 +2745,9 @@
 
                 if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
                 return hideCurrentInputLocked(flags, resultReceiver);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
             }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -2827,14 +2827,14 @@
             @SoftInputModeFlags int softInputMode, int windowFlags, EditorInfo attribute,
             IInputContext inputContext, @MissingMethodFlags int missingMethods,
             int unverifiedTargetSdkVersion) {
-        // Needs to check the validity before clearing calling identity
-        final boolean calledFromValidUser = calledFromValidUser();
         InputBindResult res = null;
-        long ident = Binder.clearCallingIdentity();
-        try {
+        synchronized (mMethodMap) {
+            // Needs to check the validity before clearing calling identity
+            final boolean calledFromValidUser = calledFromValidUserLocked();
             final int windowDisplayId =
                     mWindowManagerInternal.getDisplayIdForWindow(windowToken);
-            synchronized (mMethodMap) {
+            final long ident = Binder.clearCallingIdentity();
+            try {
                 if (DEBUG) Slog.v(TAG, "startInputOrWindowGainedFocusInternal: reason="
                         + InputMethodDebug.startInputReasonToString(startInputReason)
                         + " client=" + client.asBinder()
@@ -3023,9 +3023,9 @@
                         res = InputBindResult.NULL_EDITOR_INFO;
                     }
                 }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
             }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
         }
 
         return res;
@@ -3056,10 +3056,10 @@
     @Override
     public void showInputMethodPickerFromClient(
             IInputMethodClient client, int auxiliarySubtypeMode) {
-        if (!calledFromValidUser()) {
-            return;
-        }
         synchronized (mMethodMap) {
+            if (!calledFromValidUserLocked()) {
+                return;
+            }
             if(!canShowInputMethodPickerLocked(client)) {
                 Slog.w(TAG, "Ignoring showInputMethodPickerFromClient of uid "
                         + Binder.getCallingUid() + ": " + client);
@@ -3084,18 +3084,20 @@
 
     @Override
     public void setInputMethod(IBinder token, String id) {
-        if (!calledFromValidUser()) {
-            return;
+        synchronized (mMethodMap) {
+            if (!calledFromValidUserLocked()) {
+                return;
+            }
+            setInputMethodWithSubtypeIdLocked(token, id, NOT_A_SUBTYPE_ID);
         }
-        setInputMethodWithSubtypeId(token, id, NOT_A_SUBTYPE_ID);
     }
 
     @Override
     public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
-        if (!calledFromValidUser()) {
-            return;
-        }
         synchronized (mMethodMap) {
+            if (!calledFromValidUserLocked()) {
+                return;
+            }
             if (subtype != null) {
                 setInputMethodWithSubtypeIdLocked(token, id,
                         InputMethodUtils.getSubtypeIdFromHashCode(mMethodMap.get(id),
@@ -3109,22 +3111,22 @@
     @Override
     public void showInputMethodAndSubtypeEnablerFromClient(
             IInputMethodClient client, String inputMethodId) {
-        // TODO(yukawa): Should we verify the display ID?
-        if (!calledFromValidUser()) {
-            return;
-        }
         synchronized (mMethodMap) {
+            // TODO(yukawa): Should we verify the display ID?
+            if (!calledFromValidUserLocked()) {
+                return;
+            }
             executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
                     MSG_SHOW_IM_SUBTYPE_ENABLER, inputMethodId));
         }
     }
 
-    @Override
-    public boolean switchToPreviousInputMethod(IBinder token) {
-        if (!calledFromValidUser()) {
-            return false;
-        }
+    @BinderThread
+    private boolean switchToPreviousInputMethod(IBinder token) {
         synchronized (mMethodMap) {
+            if (!calledWithValidTokenLocked(token)) {
+                return false;
+            }
             final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
             final InputMethodInfo lastImi;
             if (lastIme != null) {
@@ -3191,13 +3193,10 @@
         }
     }
 
-    @Override
-    public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
-        if (!calledFromValidUser()) {
-            return false;
-        }
+    @BinderThread
+    private boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
         synchronized (mMethodMap) {
-            if (!calledWithValidToken(token)) {
+            if (!calledWithValidTokenLocked(token)) {
                 return false;
             }
             final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
@@ -3213,11 +3212,8 @@
 
     @BinderThread
     private boolean shouldOfferSwitchingToNextInputMethod(@NonNull IBinder token) {
-        if (!calledFromValidUser()) {
-            return false;
-        }
         synchronized (mMethodMap) {
-            if (!calledWithValidToken(token)) {
+            if (!calledWithValidTokenLocked(token)) {
                 return false;
             }
             final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
@@ -3231,10 +3227,10 @@
 
     @Override
     public InputMethodSubtype getLastInputMethodSubtype() {
-        if (!calledFromValidUser()) {
-            return null;
-        }
         synchronized (mMethodMap) {
+            if (!calledFromValidUserLocked()) {
+                return null;
+            }
             final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
             // TODO: Handle the case of the last IME with no subtypes
             if (lastIme == null || TextUtils.isEmpty(lastIme.first)
@@ -3257,13 +3253,13 @@
 
     @Override
     public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
-        if (!calledFromValidUser()) {
-            return;
-        }
         // By this IPC call, only a process which shares the same uid with the IME can add
         // additional input method subtypes to the IME.
         if (TextUtils.isEmpty(imiId) || subtypes == null) return;
         synchronized (mMethodMap) {
+            if (!calledFromValidUserLocked()) {
+                return;
+            }
             if (!mSystemReady) {
                 return;
             }
@@ -3329,12 +3325,6 @@
         }
     }
 
-    private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) {
-        synchronized (mMethodMap) {
-            setInputMethodWithSubtypeIdLocked(token, id, subtypeId);
-        }
-    }
-
     private void setInputMethodWithSubtypeIdLocked(IBinder token, String id, int subtypeId) {
         if (token == null) {
             if (mContext.checkCallingOrSelfPermission(
@@ -3360,11 +3350,8 @@
 
     @BinderThread
     private void hideMySoftInput(@NonNull IBinder token, int flags) {
-        if (!calledFromValidUser()) {
-            return;
-        }
         synchronized (mMethodMap) {
-            if (!calledWithValidToken(token)) {
+            if (!calledWithValidTokenLocked(token)) {
                 return;
             }
             long ident = Binder.clearCallingIdentity();
@@ -3378,11 +3365,8 @@
 
     @BinderThread
     private void showMySoftInput(@NonNull IBinder token, int flags) {
-        if (!calledFromValidUser()) {
-            return;
-        }
         synchronized (mMethodMap) {
-            if (!calledWithValidToken(token)) {
+            if (!calledWithValidTokenLocked(token)) {
                 return;
             }
             long ident = Binder.clearCallingIdentity();
@@ -4195,11 +4179,11 @@
      */
     @Override
     public InputMethodSubtype getCurrentInputMethodSubtype() {
-        // TODO: Make this work even for non-current users?
-        if (!calledFromValidUser()) {
-            return null;
-        }
         synchronized (mMethodMap) {
+            // TODO: Make this work even for non-current users?
+            if (!calledFromValidUserLocked()) {
+                return null;
+            }
             return getCurrentInputMethodSubtypeLocked();
         }
     }
@@ -4274,11 +4258,11 @@
 
     @Override
     public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
-        // TODO: Make this work even for non-current users?
-        if (!calledFromValidUser()) {
-            return false;
-        }
         synchronized (mMethodMap) {
+            // TODO: Make this work even for non-current users?
+            if (!calledFromValidUserLocked()) {
+                return false;
+            }
             if (subtype != null && mCurMethodId != null) {
                 InputMethodInfo imi = mMethodMap.get(mCurMethodId);
                 int subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(imi, subtype.hashCode());
@@ -4532,10 +4516,6 @@
     @BinderThread
     private IInputContentUriToken createInputContentUriToken(@Nullable IBinder token,
             @Nullable Uri contentUri, @Nullable String packageName) {
-        if (!calledFromValidUser()) {
-            return null;
-        }
-
         if (token == null) {
             throw new NullPointerException("token");
         }
@@ -4589,11 +4569,8 @@
 
     @BinderThread
     private void reportFullscreenMode(IBinder token, boolean fullscreen) {
-        if (!calledFromValidUser()) {
-            return;
-        }
         synchronized (mMethodMap) {
-            if (!calledWithValidToken(token)) {
+            if (!calledWithValidTokenLocked(token)) {
                 return;
             }
             if (mCurClient != null && mCurClient.client != null) {
@@ -4933,11 +4910,6 @@
     @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
     private int handleShellCommandEnableDisableInputMethod(
             @NonNull ShellCommand shellCommand, boolean enabled) {
-        if (!calledFromValidUser()) {
-            shellCommand.getErrPrintWriter().print(
-                    "Must be called from the foreground user or with INTERACT_ACROSS_USERS_FULL");
-            return ShellCommandResult.FAILURE;
-        }
         final String id = shellCommand.getNextArgRequired();
 
         final boolean previouslyEnabled;
@@ -4994,11 +4966,6 @@
     @ShellCommandResult
     @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
     private int handleShellCommandResetInputMethod(@NonNull ShellCommand shellCommand) {
-        if (!calledFromValidUser()) {
-            shellCommand.getErrPrintWriter().print(
-                    "Must be called from the foreground user or with INTERACT_ACROSS_USERS_FULL");
-            return ShellCommandResult.FAILURE;
-        }
         synchronized (mMethodMap) {
             if (mContext.checkCallingOrSelfPermission(
                     android.Manifest.permission.WRITE_SECURE_SETTINGS)
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 2b67fe7..128d4d4 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -1595,20 +1595,6 @@
 
         @BinderThread
         @Override
-        public boolean switchToPreviousInputMethod(IBinder token) {
-            reportNotSupported();
-            return false;
-        }
-
-        @BinderThread
-        @Override
-        public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
-            reportNotSupported();
-            return false;
-        }
-
-        @BinderThread
-        @Override
         public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
             reportNotSupported();
         }
diff --git a/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java b/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
deleted file mode 100644
index f424869..0000000
--- a/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
+++ /dev/null
@@ -1,84 +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.server.intelligence;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UserIdInt;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-
-/**
- * Intelligence Manager local system service interface.
- *
- * @hide Only for use within the system server.
- */
-//TODO(b/111276913): rename once the final name is defined
-public abstract class IntelligenceManagerInternal {
-
-    /**
-     * Checks whether the given {@code uid} owns the
-     * {@link android.service.intelligence.SmartSuggestionsService} implementation associated with
-     * the given {@code userId}.
-     */
-    public abstract boolean isIntelligenceServiceForUser(int uid, @UserIdInt int userId);
-
-    /**
-     * Notifies the intelligence service of new assist data for the given activity.
-     *
-     * @return {@code false} if there was no service set for the given user
-     */
-    public abstract boolean sendActivityAssistData(@UserIdInt int userId,
-            @NonNull IBinder activityToken, @NonNull Bundle data);
-
-    /**
-     * Asks the intelligence service to provide Augmented Autofill for a given activity.
-     *
-     * @param userId user handle
-     * @param client binder used to communicate with the activity that originated this request.
-     * @param activityToken activity that originated this request.
-     * @param autofillSessionId autofill session id (must be used on {@code client} calls.
-     * @param focusedId id of the the field that triggered this request.
-     * @param focusedValue current value of the field that triggered this request.
-     *
-     * @return {@code false} if the service cannot handle this request, {@code true} otherwise.
-     * <b>NOTE: </b> it must return right away; typically it will return {@code false} if the
-     * service is disabled (or the activity blacklisted).
-     */
-    public abstract AugmentedAutofillCallback requestAutofill(@UserIdInt int userId,
-            @NonNull IAutoFillManagerClient client, @NonNull IBinder activityToken,
-            int autofillSessionId, @NonNull AutofillId focusedId,
-            @Nullable AutofillValue focusedValue);
-
-    /**
-     * Callback used by the Autofill Session to communicate with the Augmented Autofill service.
-     */
-    public interface AugmentedAutofillCallback {
-        // TODO(b/111330312): this method is calling when the Autofill session is destroyed, the
-        // main reason being the cases where user tap HOME.
-        // Right now it's completely destroying the UI, but we need to decide whether / how to
-        // properly recover it later (for example, if the user switches back to the activity,
-        // should it be restored? Right not it kind of is, because Autofill's Session trigger a
-        // new FillRequest, which in turn triggers the Augmented Autofill request again)
-        /**
-         * Destroys the Autofill UI.
-         */
-        void destroy();
-    }
-}
diff --git a/services/core/java/com/android/server/job/JobConcurrencyManager.java b/services/core/java/com/android/server/job/JobConcurrencyManager.java
new file mode 100644
index 0000000..ee1d847
--- /dev/null
+++ b/services/core/java/com/android/server/job/JobConcurrencyManager.java
@@ -0,0 +1,251 @@
+/*
+ * 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.server.job;
+
+import android.app.ActivityManager;
+import android.app.job.JobInfo;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.app.procstats.ProcessStats;
+import com.android.server.job.controllers.JobStatus;
+import com.android.server.job.controllers.StateController;
+
+import java.util.Iterator;
+import java.util.List;
+
+class JobConcurrencyManager {
+    private static final String TAG = JobSchedulerService.TAG;
+    private static final boolean DEBUG = JobSchedulerService.DEBUG;
+
+    private final Object mLock;
+    private final JobSchedulerService mService;
+    private final JobSchedulerService.Constants mConstants;
+
+    private static final int MAX_JOB_CONTEXTS_COUNT = JobSchedulerService.MAX_JOB_CONTEXTS_COUNT;
+
+    /**
+     * This array essentially stores the state of mActiveServices array.
+     * The ith index stores the job present on the ith JobServiceContext.
+     * We manipulate this array until we arrive at what jobs should be running on
+     * what JobServiceContext.
+     */
+    JobStatus[] mTmpAssignContextIdToJobMap = new JobStatus[MAX_JOB_CONTEXTS_COUNT];
+
+    /**
+     * Indicates whether we need to act on this jobContext id
+     */
+    boolean[] mTmpAssignAct = new boolean[MAX_JOB_CONTEXTS_COUNT];
+
+    /**
+     * The uid whose jobs we would like to assign to a context.
+     */
+    int[] mTmpAssignPreferredUidForContext = new int[MAX_JOB_CONTEXTS_COUNT];
+
+    JobConcurrencyManager(JobSchedulerService service) {
+        mService = service;
+        mLock = mService.mLock;
+        mConstants = service.mConstants;
+    }
+
+    /**
+     * Takes jobs from pending queue and runs them on available contexts.
+     * If no contexts are available, preempts lower priority jobs to
+     * run higher priority ones.
+     * Lock on mJobs before calling this function.
+     */
+    void assignJobsToContextsLocked() {
+        if (DEBUG) {
+            Slog.d(TAG, printPendingQueueLocked());
+        }
+
+        final JobPackageTracker tracker = mService.mJobPackageTracker;
+        final List<JobStatus> pendingJobs = mService.mPendingJobs;
+        final List<JobServiceContext> activeServices = mService.mActiveServices;
+        final List<StateController> controllers = mService.mControllers;
+
+        int memLevel;
+        try {
+            memLevel = ActivityManager.getService().getMemoryTrimLevel();
+        } catch (RemoteException e) {
+            memLevel = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+        }
+        switch (memLevel) {
+            case ProcessStats.ADJ_MEM_FACTOR_MODERATE:
+                mService.mMaxActiveJobs = mConstants.BG_MODERATE_JOB_COUNT;
+                break;
+            case ProcessStats.ADJ_MEM_FACTOR_LOW:
+                mService.mMaxActiveJobs = mConstants.BG_LOW_JOB_COUNT;
+                break;
+            case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
+                mService.mMaxActiveJobs = mConstants.BG_CRITICAL_JOB_COUNT;
+                break;
+            default:
+                mService.mMaxActiveJobs = mConstants.BG_NORMAL_JOB_COUNT;
+                break;
+        }
+
+        JobStatus[] contextIdToJobMap = mTmpAssignContextIdToJobMap;
+        boolean[] act = mTmpAssignAct;
+        int[] preferredUidForContext = mTmpAssignPreferredUidForContext;
+        int numActive = 0;
+        int numForeground = 0;
+        for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
+            final JobServiceContext js = mService.mActiveServices.get(i);
+            final JobStatus status = js.getRunningJobLocked();
+            if ((contextIdToJobMap[i] = status) != null) {
+                numActive++;
+                if (status.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
+                    numForeground++;
+                }
+            }
+            act[i] = false;
+            preferredUidForContext[i] = js.getPreferredUid();
+        }
+        if (DEBUG) {
+            Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs initial"));
+        }
+        for (int i=0; i<pendingJobs.size(); i++) {
+            JobStatus nextPending = pendingJobs.get(i);
+
+            // If job is already running, go to next job.
+            int jobRunningContext = findJobContextIdFromMap(nextPending, contextIdToJobMap);
+            if (jobRunningContext != -1) {
+                continue;
+            }
+
+            final int priority = mService.evaluateJobPriorityLocked(nextPending);
+            nextPending.lastEvaluatedPriority = priority;
+
+            // Find a context for nextPending. The context should be available OR
+            // it should have lowest priority among all running jobs
+            // (sharing the same Uid as nextPending)
+            int minPriority = Integer.MAX_VALUE;
+            int minPriorityContextId = -1;
+            for (int j=0; j<MAX_JOB_CONTEXTS_COUNT; j++) {
+                JobStatus job = contextIdToJobMap[j];
+                int preferredUid = preferredUidForContext[j];
+                if (job == null) {
+                    if ((numActive < mService.mMaxActiveJobs ||
+                            (priority >= JobInfo.PRIORITY_TOP_APP &&
+                                    numForeground < mConstants.FG_JOB_COUNT)) &&
+                            (preferredUid == nextPending.getUid() ||
+                                    preferredUid == JobServiceContext.NO_PREFERRED_UID)) {
+                        // This slot is free, and we haven't yet hit the limit on
+                        // concurrent jobs...  we can just throw the job in to here.
+                        minPriorityContextId = j;
+                        break;
+                    }
+                    // No job on this context, but nextPending can't run here because
+                    // the context has a preferred Uid or we have reached the limit on
+                    // concurrent jobs.
+                    continue;
+                }
+                if (job.getUid() != nextPending.getUid()) {
+                    continue;
+                }
+                if (mService.evaluateJobPriorityLocked(job) >= nextPending.lastEvaluatedPriority) {
+                    continue;
+                }
+                if (minPriority > nextPending.lastEvaluatedPriority) {
+                    minPriority = nextPending.lastEvaluatedPriority;
+                    minPriorityContextId = j;
+                }
+            }
+            if (minPriorityContextId != -1) {
+                contextIdToJobMap[minPriorityContextId] = nextPending;
+                act[minPriorityContextId] = true;
+                numActive++;
+                if (priority >= JobInfo.PRIORITY_TOP_APP) {
+                    numForeground++;
+                }
+            }
+        }
+        if (DEBUG) {
+            Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs final"));
+        }
+        tracker.noteConcurrency(numActive, numForeground);
+        for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
+            boolean preservePreferredUid = false;
+            if (act[i]) {
+                JobStatus js = activeServices.get(i).getRunningJobLocked();
+                if (js != null) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "preempting job: "
+                                + activeServices.get(i).getRunningJobLocked());
+                    }
+                    // preferredUid will be set to uid of currently running job.
+                    activeServices.get(i).preemptExecutingJobLocked();
+                    preservePreferredUid = true;
+                } else {
+                    final JobStatus pendingJob = contextIdToJobMap[i];
+                    if (DEBUG) {
+                        Slog.d(TAG, "About to run job on context "
+                                + String.valueOf(i) + ", job: " + pendingJob);
+                    }
+                    for (int ic=0; ic<controllers.size(); ic++) {
+                        controllers.get(ic).prepareForExecutionLocked(pendingJob);
+                    }
+                    if (!activeServices.get(i).executeRunnableJob(pendingJob)) {
+                        Slog.d(TAG, "Error executing " + pendingJob);
+                    }
+                    if (pendingJobs.remove(pendingJob)) {
+                        tracker.noteNonpending(pendingJob);
+                    }
+                }
+            }
+            if (!preservePreferredUid) {
+                activeServices.get(i).clearPreferredUid();
+            }
+        }
+    }
+
+    int findJobContextIdFromMap(JobStatus jobStatus, JobStatus[] map) {
+        for (int i=0; i<map.length; i++) {
+            if (map[i] != null && map[i].matches(jobStatus.getUid(), jobStatus.getJobId())) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private String printPendingQueueLocked() {
+        StringBuilder s = new StringBuilder("Pending queue: ");
+        Iterator<JobStatus> it = mService.mPendingJobs.iterator();
+        while (it.hasNext()) {
+            JobStatus js = it.next();
+            s.append("(")
+                    .append(js.getJob().getId())
+                    .append(", ")
+                    .append(js.getUid())
+                    .append(") ");
+        }
+        return s.toString();
+    }
+
+    private String printContextIdToJobMap(JobStatus[] map, String initial) {
+        StringBuilder s = new StringBuilder(initial + ": ");
+        for (int i=0; i<map.length; i++) {
+            s.append("(")
+                    .append(map[i] == null? -1: map[i].getJobId())
+                    .append(map[i] == null? -1: map[i].getUid())
+                    .append(")" );
+        }
+        return s.toString();
+    }
+
+}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index ea295de..611c8b7 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -54,6 +54,8 @@
 import android.os.BatteryStatsInternal;
 import android.os.Binder;
 import android.os.Handler;
+import android.os.IThermalService;
+import android.os.IThermalStatusListener;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
@@ -62,6 +64,7 @@
 import android.os.ServiceManager;
 import android.os.ShellCallback;
 import android.os.SystemClock;
+import android.os.Temperature;
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
 import android.provider.Settings;
@@ -75,9 +78,9 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
-import com.android.internal.app.procstats.ProcessStats;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
@@ -111,7 +114,6 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
@@ -135,7 +137,7 @@
     public static final boolean DEBUG_STANDBY = DEBUG || false;
 
     /** The maximum number of concurrent jobs we run at one time. */
-    private static final int MAX_JOB_CONTEXTS_COUNT = 16;
+    static final int MAX_JOB_CONTEXTS_COUNT = 16;
     /** Enforce a per-app limit on scheduled jobs? */
     private static final boolean ENFORCE_MAX_JOBS = true;
     /** The maximum number of jobs that we allow an unprivileged app to schedule */
@@ -156,6 +158,7 @@
     final StandbyTracker mStandbyTracker;
     /** Tracking amount of time each package runs for. */
     final JobPackageTracker mJobPackageTracker = new JobPackageTracker();
+    final JobConcurrencyManager mConcurrencyManager;
 
     static final int MSG_JOB_EXPIRED = 0;
     static final int MSG_CHECK_JOB = 1;
@@ -173,13 +176,18 @@
     final List<JobServiceContext> mActiveServices = new ArrayList<>();
 
     /** List of controllers that will notify this service of updates to jobs. */
-    private final List<StateController> mControllers;
+    final List<StateController> mControllers;
     /** Need direct access to this for testing. */
     private final BatteryController mBatteryController;
     /** Need direct access to this for testing. */
     private final StorageController mStorageController;
     /** Need directly for sending uid state changes */
     private final DeviceIdleJobsController mDeviceIdleJobsController;
+    /** Need directly for receiving thermal events */
+    private IThermalService mThermalService;
+    /** Thermal constraint. */
+    @GuardedBy("mLock")
+    private boolean mThermalConstraint = false;
 
     /**
      * Queue of pending jobs. The JobServiceContext class will receive jobs from this list
@@ -268,22 +276,6 @@
 
     // -- Pre-allocated temporaries only for use in assignJobsToContextsLocked --
 
-    /**
-     * This array essentially stores the state of mActiveServices array.
-     * The ith index stores the job present on the ith JobServiceContext.
-     * We manipulate this array until we arrive at what jobs should be running on
-     * what JobServiceContext.
-     */
-    JobStatus[] mTmpAssignContextIdToJobMap = new JobStatus[MAX_JOB_CONTEXTS_COUNT];
-    /**
-     * Indicates whether we need to act on this jobContext id
-     */
-    boolean[] mTmpAssignAct = new boolean[MAX_JOB_CONTEXTS_COUNT];
-    /**
-     * The uid whose jobs we would like to assign to a context.
-     */
-    int[] mTmpAssignPreferredUidForContext = new int[MAX_JOB_CONTEXTS_COUNT];
-
     private class ConstantsObserver extends ContentObserver {
         private ContentResolver mResolver;
 
@@ -327,6 +319,19 @@
     }
 
     /**
+     *  Thermal event received from Thermal Service
+     */
+    private final class ThermalStatusListener extends IThermalStatusListener.Stub {
+        @Override public void onStatusChange(int status) {
+            // Throttle for Temperature.THROTTLING_SEVERE and above
+            synchronized (mLock) {
+                mThermalConstraint = status >= Temperature.THROTTLING_SEVERE;
+            }
+            onControllerStateChanged();
+        }
+    }
+
+    /**
      * All times are in milliseconds. These constants are kept synchronized with the system
      * global Settings. Any access to this class or its fields should be done while
      * holding the JobSchedulerService.mLock lock.
@@ -1176,8 +1181,10 @@
                 // with just the foreground priority.  This means that persistent processes
                 // can never be the top app priority...  that is fine.
                 mUidPriorityOverride.put(uid, JobInfo.PRIORITY_TOP_APP);
+            } else if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
+                mUidPriorityOverride.put(uid, JobInfo.PRIORITY_FOREGROUND_SERVICE);
             } else if (procState <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
-                mUidPriorityOverride.put(uid, JobInfo.PRIORITY_FOREGROUND_APP);
+                mUidPriorityOverride.put(uid, JobInfo.PRIORITY_BOUND_FOREGROUND_SERVICE);
             } else {
                 mUidPriorityOverride.delete(uid);
             }
@@ -1267,6 +1274,8 @@
         mConstantsObserver = new ConstantsObserver(mHandler);
         mJobSchedulerStub = new JobSchedulerStub();
 
+        mConcurrencyManager = new JobConcurrencyManager(this);
+
         // Set up the app standby bucketing tracker
         mStandbyTracker = new StandbyTracker();
         mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
@@ -1381,6 +1390,16 @@
             }
             // Remove any jobs that are not associated with any of the current users.
             cancelJobsForNonExistentUsers();
+            // Register thermal callback
+            mThermalService = IThermalService.Stub.asInterface(
+                    ServiceManager.getService(Context.THERMAL_SERVICE));
+            if (mThermalService != null) {
+                try {
+                    mThermalService.registerThermalStatusListener(new ThermalStatusListener());
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to register thermal callback.", e);
+                }
+            }
         } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
             synchronized (mLock) {
                 // Let's go!
@@ -1804,14 +1823,26 @@
         }
     }
 
+    private boolean isJobThermalConstrainedLocked(JobStatus job) {
+        return mThermalConstraint && job.hasConnectivityConstraint()
+                && (evaluateJobPriorityLocked(job) < JobInfo.PRIORITY_FOREGROUND_APP);
+    }
+
     private void stopNonReadyActiveJobsLocked() {
         for (int i=0; i<mActiveServices.size(); i++) {
             JobServiceContext serviceContext = mActiveServices.get(i);
             final JobStatus running = serviceContext.getRunningJobLocked();
-            if (running != null && !running.isReady()) {
+            if (running == null) {
+                continue;
+            }
+            if (!running.isReady()) {
                 serviceContext.cancelExecutingJobLocked(
                         JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED,
                         "cancelled due to unsatisfied constraints");
+            } else if (isJobThermalConstrainedLocked(running)) {
+                serviceContext.cancelExecutingJobLocked(
+                        JobParameters.REASON_DEVICE_THERMAL,
+                        "cancelled due to thermal condition");
             }
         }
     }
@@ -2099,6 +2130,10 @@
             return false;
         }
 
+        if (isJobThermalConstrainedLocked(job)) {
+            return false;
+        }
+
         final boolean jobPending = mPendingJobs.contains(job);
         final boolean jobActive = isCurrentlyActiveLocked(job);
 
@@ -2193,7 +2228,7 @@
         if (DEBUG) {
             Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs.");
         }
-        assignJobsToContextsLocked();
+        mConcurrencyManager.assignJobsToContextsLocked();
         reportActiveLocked();
     }
 
@@ -2209,9 +2244,9 @@
         return curPriority;
     }
 
-    private int evaluateJobPriorityLocked(JobStatus job) {
+    int evaluateJobPriorityLocked(JobStatus job) {
         int priority = job.getPriority();
-        if (priority >= JobInfo.PRIORITY_FOREGROUND_APP) {
+        if (priority >= JobInfo.PRIORITY_BOUND_FOREGROUND_SERVICE) {
             return adjustJobPriority(priority, job);
         }
         int override = mUidPriorityOverride.get(job.getSourceUid(), 0);
@@ -2221,161 +2256,6 @@
         return adjustJobPriority(priority, job);
     }
 
-    /**
-     * Takes jobs from pending queue and runs them on available contexts.
-     * If no contexts are available, preempts lower priority jobs to
-     * run higher priority ones.
-     * Lock on mJobs before calling this function.
-     */
-    private void assignJobsToContextsLocked() {
-        if (DEBUG) {
-            Slog.d(TAG, printPendingQueue());
-        }
-
-        int memLevel;
-        try {
-            memLevel = ActivityManager.getService().getMemoryTrimLevel();
-        } catch (RemoteException e) {
-            memLevel = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
-        }
-        switch (memLevel) {
-            case ProcessStats.ADJ_MEM_FACTOR_MODERATE:
-                mMaxActiveJobs = mConstants.BG_MODERATE_JOB_COUNT;
-                break;
-            case ProcessStats.ADJ_MEM_FACTOR_LOW:
-                mMaxActiveJobs = mConstants.BG_LOW_JOB_COUNT;
-                break;
-            case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
-                mMaxActiveJobs = mConstants.BG_CRITICAL_JOB_COUNT;
-                break;
-            default:
-                mMaxActiveJobs = mConstants.BG_NORMAL_JOB_COUNT;
-                break;
-        }
-
-        JobStatus[] contextIdToJobMap = mTmpAssignContextIdToJobMap;
-        boolean[] act = mTmpAssignAct;
-        int[] preferredUidForContext = mTmpAssignPreferredUidForContext;
-        int numActive = 0;
-        int numForeground = 0;
-        for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
-            final JobServiceContext js = mActiveServices.get(i);
-            final JobStatus status = js.getRunningJobLocked();
-            if ((contextIdToJobMap[i] = status) != null) {
-                numActive++;
-                if (status.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
-                    numForeground++;
-                }
-            }
-            act[i] = false;
-            preferredUidForContext[i] = js.getPreferredUid();
-        }
-        if (DEBUG) {
-            Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs initial"));
-        }
-        for (int i=0; i<mPendingJobs.size(); i++) {
-            JobStatus nextPending = mPendingJobs.get(i);
-
-            // If job is already running, go to next job.
-            int jobRunningContext = findJobContextIdFromMap(nextPending, contextIdToJobMap);
-            if (jobRunningContext != -1) {
-                continue;
-            }
-
-            final int priority = evaluateJobPriorityLocked(nextPending);
-            nextPending.lastEvaluatedPriority = priority;
-
-            // Find a context for nextPending. The context should be available OR
-            // it should have lowest priority among all running jobs
-            // (sharing the same Uid as nextPending)
-            int minPriority = Integer.MAX_VALUE;
-            int minPriorityContextId = -1;
-            for (int j=0; j<MAX_JOB_CONTEXTS_COUNT; j++) {
-                JobStatus job = contextIdToJobMap[j];
-                int preferredUid = preferredUidForContext[j];
-                if (job == null) {
-                    if ((numActive < mMaxActiveJobs ||
-                            (priority >= JobInfo.PRIORITY_TOP_APP &&
-                                    numForeground < mConstants.FG_JOB_COUNT)) &&
-                            (preferredUid == nextPending.getUid() ||
-                                    preferredUid == JobServiceContext.NO_PREFERRED_UID)) {
-                        // This slot is free, and we haven't yet hit the limit on
-                        // concurrent jobs...  we can just throw the job in to here.
-                        minPriorityContextId = j;
-                        break;
-                    }
-                    // No job on this context, but nextPending can't run here because
-                    // the context has a preferred Uid or we have reached the limit on
-                    // concurrent jobs.
-                    continue;
-                }
-                if (job.getUid() != nextPending.getUid()) {
-                    continue;
-                }
-                if (evaluateJobPriorityLocked(job) >= nextPending.lastEvaluatedPriority) {
-                    continue;
-                }
-                if (minPriority > nextPending.lastEvaluatedPriority) {
-                    minPriority = nextPending.lastEvaluatedPriority;
-                    minPriorityContextId = j;
-                }
-            }
-            if (minPriorityContextId != -1) {
-                contextIdToJobMap[minPriorityContextId] = nextPending;
-                act[minPriorityContextId] = true;
-                numActive++;
-                if (priority >= JobInfo.PRIORITY_TOP_APP) {
-                    numForeground++;
-                }
-            }
-        }
-        if (DEBUG) {
-            Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs final"));
-        }
-        mJobPackageTracker.noteConcurrency(numActive, numForeground);
-        for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
-            boolean preservePreferredUid = false;
-            if (act[i]) {
-                JobStatus js = mActiveServices.get(i).getRunningJobLocked();
-                if (js != null) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "preempting job: " + mActiveServices.get(i).getRunningJobLocked());
-                    }
-                    // preferredUid will be set to uid of currently running job.
-                    mActiveServices.get(i).preemptExecutingJobLocked();
-                    preservePreferredUid = true;
-                } else {
-                    final JobStatus pendingJob = contextIdToJobMap[i];
-                    if (DEBUG) {
-                        Slog.d(TAG, "About to run job on context "
-                                + String.valueOf(i) + ", job: " + pendingJob);
-                    }
-                    for (int ic=0; ic<mControllers.size(); ic++) {
-                        mControllers.get(ic).prepareForExecutionLocked(pendingJob);
-                    }
-                    if (!mActiveServices.get(i).executeRunnableJob(pendingJob)) {
-                        Slog.d(TAG, "Error executing " + pendingJob);
-                    }
-                    if (mPendingJobs.remove(pendingJob)) {
-                        mJobPackageTracker.noteNonpending(pendingJob);
-                    }
-                }
-            }
-            if (!preservePreferredUid) {
-                mActiveServices.get(i).clearPreferredUid();
-            }
-        }
-    }
-
-    int findJobContextIdFromMap(JobStatus jobStatus, JobStatus[] map) {
-        for (int i=0; i<map.length; i++) {
-            if (map[i] != null && map[i].matches(jobStatus.getUid(), jobStatus.getJobId())) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
     final class LocalService implements JobSchedulerInternal {
 
         /**
@@ -3150,31 +3030,6 @@
         getContext().sendBroadcastAsUser(dockIntent, UserHandle.ALL);
     }
 
-    private String printContextIdToJobMap(JobStatus[] map, String initial) {
-        StringBuilder s = new StringBuilder(initial + ": ");
-        for (int i=0; i<map.length; i++) {
-            s.append("(")
-                    .append(map[i] == null? -1: map[i].getJobId())
-                    .append(map[i] == null? -1: map[i].getUid())
-                    .append(")" );
-        }
-        return s.toString();
-    }
-
-    private String printPendingQueue() {
-        StringBuilder s = new StringBuilder("Pending queue: ");
-        Iterator<JobStatus> it = mPendingJobs.iterator();
-        while (it.hasNext()) {
-            JobStatus js = it.next();
-            s.append("(")
-                    .append(js.getJob().getId())
-                    .append(", ")
-                    .append(js.getUid())
-                    .append(") ");
-        }
-        return s.toString();
-    }
-
     static void dumpHelp(PrintWriter pw) {
         pw.println("Job Scheduler (jobscheduler) dump options:");
         pw.println("  [-h] [package] ...");
@@ -3228,6 +3083,9 @@
             pw.print("    In parole?: ");
             pw.print(mInParole);
             pw.println();
+            pw.print("    In thermal throttling?: ");
+            pw.print(mThermalConstraint);
+            pw.println();
             pw.println();
 
             pw.println("Started users: " + Arrays.toString(mStartedUsers));
@@ -3325,9 +3183,9 @@
                 pw.println(job.toShortString());
                 job.dump(pw, "    ", false, nowElapsed);
                 int priority = evaluateJobPriorityLocked(job);
-                if (priority != JobInfo.PRIORITY_DEFAULT) {
-                    pw.print("    Evaluated priority: "); pw.println(priority);
-                }
+                pw.print("    Evaluated priority: ");
+                pw.println(JobInfo.getPriorityString(priority));
+
                 pw.print("    Tag: "); pw.println(job.getTag());
                 pw.print("    Enq: ");
                 TimeUtils.formatDuration(job.madePending - nowUptime, pw);
@@ -3358,9 +3216,9 @@
                     pw.println();
                     job.dump(pw, "    ", false, nowElapsed);
                     int priority = evaluateJobPriorityLocked(jsc.getRunningJobLocked());
-                    if (priority != JobInfo.PRIORITY_DEFAULT) {
-                        pw.print("    Evaluated priority: "); pw.println(priority);
-                    }
+                    pw.print("    Evaluated priority: ");
+                    pw.println(JobInfo.getPriorityString(priority));
+
                     pw.print("    Active at ");
                     TimeUtils.formatDuration(job.madeActive - nowUptime, pw);
                     pw.print(", pending for ");
@@ -3403,6 +3261,7 @@
             proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT_TIME_MILLIS,
                     mLastHeartbeatTime + mConstants.STANDBY_HEARTBEAT_TIME - nowUptime);
             proto.write(JobSchedulerServiceDumpProto.IN_PAROLE, mInParole);
+            proto.write(JobSchedulerServiceDumpProto.IN_THERMAL, mThermalConstraint);
 
             for (int u : mStartedUsers) {
                 proto.write(JobSchedulerServiceDumpProto.STARTED_USERS, u);
@@ -3478,10 +3337,7 @@
 
                 job.writeToShortProto(proto, PendingJob.INFO);
                 job.dump(proto, PendingJob.DUMP, false, nowElapsed);
-                int priority = evaluateJobPriorityLocked(job);
-                if (priority != JobInfo.PRIORITY_DEFAULT) {
-                    proto.write(PendingJob.EVALUATED_PRIORITY, priority);
-                }
+                proto.write(PendingJob.EVALUATED_PRIORITY, evaluateJobPriorityLocked(job));
                 proto.write(PendingJob.ENQUEUED_DURATION_MS, nowUptime - job.madePending);
 
                 proto.end(pjToken);
@@ -3513,10 +3369,8 @@
 
                     job.dump(proto, ActiveJob.RunningJob.DUMP, false, nowElapsed);
 
-                    int priority = evaluateJobPriorityLocked(jsc.getRunningJobLocked());
-                    if (priority != JobInfo.PRIORITY_DEFAULT) {
-                        proto.write(ActiveJob.RunningJob.EVALUATED_PRIORITY, priority);
-                    }
+                    proto.write(ActiveJob.RunningJob.EVALUATED_PRIORITY,
+                            evaluateJobPriorityLocked(jsc.getRunningJobLocked()));
 
                     proto.write(ActiveJob.RunningJob.TIME_SINCE_MADE_ACTIVE_MS,
                             nowUptime - job.madeActive);
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 6deecbd..4341589 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -1321,7 +1321,8 @@
                 pw.print(prefix); pw.println("  PERSISTED");
             }
             if (job.getPriority() != 0) {
-                pw.print(prefix); pw.print("  Priority: "); pw.println(job.getPriority());
+                pw.print(prefix); pw.print("  Priority: ");
+                pw.println(JobInfo.getPriorityString(job.getPriority()));
             }
             if (job.getFlags() != 0) {
                 pw.print(prefix); pw.print("  Flags: ");
diff --git a/services/core/java/com/android/server/location/ContextHubClientBroker.java b/services/core/java/com/android/server/location/ContextHubClientBroker.java
index 6612d02..675e59e 100644
--- a/services/core/java/com/android/server/location/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/ContextHubClientBroker.java
@@ -237,7 +237,7 @@
         Supplier<Intent> supplier =
                 () -> createIntent(ContextHubManager.EVENT_NANOAPP_MESSAGE, message.getNanoAppId())
                         .putExtra(ContextHubManager.EXTRA_MESSAGE, message);
-        sendPendingIntent(supplier);
+        sendPendingIntent(supplier, message.getNanoAppId());
     }
 
     /**
@@ -247,7 +247,8 @@
      */
     /* package */ void onNanoAppLoaded(long nanoAppId) {
         invokeCallback(callback -> callback.onNanoAppLoaded(nanoAppId));
-        sendPendingIntent(() -> createIntent(ContextHubManager.EVENT_NANOAPP_LOADED, nanoAppId));
+        sendPendingIntent(
+                () -> createIntent(ContextHubManager.EVENT_NANOAPP_LOADED, nanoAppId), nanoAppId);
     }
 
     /**
@@ -257,7 +258,8 @@
      */
     /* package */ void onNanoAppUnloaded(long nanoAppId) {
         invokeCallback(callback -> callback.onNanoAppUnloaded(nanoAppId));
-        sendPendingIntent(() -> createIntent(ContextHubManager.EVENT_NANOAPP_UNLOADED, nanoAppId));
+        sendPendingIntent(
+                () -> createIntent(ContextHubManager.EVENT_NANOAPP_UNLOADED, nanoAppId), nanoAppId);
     }
 
     /**
@@ -280,7 +282,7 @@
         Supplier<Intent> supplier =
                 () -> createIntent(ContextHubManager.EVENT_NANOAPP_ABORTED, nanoAppId)
                         .putExtra(ContextHubManager.EXTRA_NANOAPP_ABORT_CODE, abortCode);
-        sendPendingIntent(supplier);
+        sendPendingIntent(supplier, nanoAppId);
     }
 
     /**
@@ -360,18 +362,40 @@
      */
     private synchronized void sendPendingIntent(Supplier<Intent> supplier) {
         if (mPendingIntentRequest.hasPendingIntent()) {
-            Intent intent = supplier.get();
-            try {
-                mPendingIntentRequest.getPendingIntent().send(
-                        mContext, 0 /* code */, intent, null /* onFinished */, null /* Handler */,
-                        Manifest.permission.LOCATION_HARDWARE /* requiredPermission */,
-                        null /* options */);
-            } catch (PendingIntent.CanceledException e) {
-                // The PendingIntent is no longer valid
-                Log.w(TAG, "PendingIntent has been canceled, unregistering from client"
-                        + " (host endpoint ID " + mHostEndPointId + ")");
-                close();
-            }
+            doSendPendingIntent(mPendingIntentRequest.getPendingIntent(), supplier.get());
+        }
+    }
+
+    /**
+     * Sends an intent to any existing PendingIntent
+     *
+     * @param supplier method to create the extra Intent
+     * @param nanoAppId the ID of the nanoapp which this event is for
+     */
+    private synchronized void sendPendingIntent(Supplier<Intent> supplier, long nanoAppId) {
+        if (mPendingIntentRequest.hasPendingIntent()
+                && mPendingIntentRequest.getNanoAppId() == nanoAppId) {
+            doSendPendingIntent(mPendingIntentRequest.getPendingIntent(), supplier.get());
+        }
+    }
+
+    /**
+     * Sends a PendingIntent with extra Intent data
+     *
+     * @param pendingIntent the PendingIntent
+     * @param intent the extra Intent data
+     */
+    private void doSendPendingIntent(PendingIntent pendingIntent, Intent intent) {
+        try {
+            pendingIntent.send(
+                    mContext, 0 /* code */, intent, null /* onFinished */, null /* Handler */,
+                    Manifest.permission.LOCATION_HARDWARE /* requiredPermission */,
+                    null /* options */);
+        } catch (PendingIntent.CanceledException e) {
+            // The PendingIntent is no longer valid
+            Log.w(TAG, "PendingIntent has been canceled, unregistering from client"
+                    + " (host endpoint ID " + mHostEndPointId + ")");
+            close();
         }
     }
 
diff --git a/services/core/java/com/android/server/location/GnssGeofenceProvider.java b/services/core/java/com/android/server/location/GnssGeofenceProvider.java
index 6ac4aeb..a84b0b1 100644
--- a/services/core/java/com/android/server/location/GnssGeofenceProvider.java
+++ b/services/core/java/com/android/server/location/GnssGeofenceProvider.java
@@ -1,18 +1,12 @@
 package com.android.server.location;
 
 import android.location.IGpsGeofenceHardware;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
 import android.util.Log;
 import android.util.SparseArray;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.FutureTask;
-
 /**
  * Manages GNSS Geofence operations.
  */
@@ -34,26 +28,26 @@
         public boolean paused;
     }
 
+    private final Object mLock = new Object();
+    @GuardedBy("mLock")
     private final GnssGeofenceProviderNative mNative;
+    @GuardedBy("mLock")
     private final SparseArray<GeofenceEntry> mGeofenceEntries = new SparseArray<>();
-    private final Handler mHandler;
 
-    GnssGeofenceProvider(Looper looper) {
-        this(looper, new GnssGeofenceProviderNative());
+    GnssGeofenceProvider() {
+        this(new GnssGeofenceProviderNative());
     }
 
     @VisibleForTesting
-    GnssGeofenceProvider(Looper looper, GnssGeofenceProviderNative gnssGeofenceProviderNative) {
-        mHandler = new Handler(looper);
+    GnssGeofenceProvider(GnssGeofenceProviderNative gnssGeofenceProviderNative) {
         mNative = gnssGeofenceProviderNative;
     }
 
-    // TODO(b/37460011): use this method in HAL death recovery.
     void resumeIfStarted() {
         if (DEBUG) {
             Log.d(TAG, "resumeIfStarted");
         }
-        mHandler.post(() -> {
+        synchronized (mLock) {
             for (int i = 0; i < mGeofenceEntries.size(); i++) {
                 GeofenceEntry entry = mGeofenceEntries.valueAt(i);
                 boolean added = mNative.addGeofence(entry.geofenceId, entry.latitude,
@@ -65,30 +59,21 @@
                     mNative.pauseGeofence(entry.geofenceId);
                 }
             }
-        });
-    }
-
-    private boolean runOnHandlerThread(Callable<Boolean> callable) {
-        FutureTask<Boolean> futureTask = new FutureTask<>(callable);
-        mHandler.post(futureTask);
-        try {
-            return futureTask.get();
-        } catch (InterruptedException | ExecutionException e) {
-            Log.e(TAG, "Failed running callable.", e);
         }
-        return false;
     }
 
     @Override
     public boolean isHardwareGeofenceSupported() {
-        return runOnHandlerThread(mNative::isGeofenceSupported);
+        synchronized (mLock) {
+            return mNative.isGeofenceSupported();
+        }
     }
 
     @Override
     public boolean addCircularHardwareGeofence(int geofenceId, double latitude,
             double longitude, double radius, int lastTransition, int monitorTransitions,
             int notificationResponsiveness, int unknownTimer) {
-        return runOnHandlerThread(() -> {
+        synchronized (mLock) {
             boolean added = mNative.addGeofence(geofenceId, latitude, longitude, radius,
                     lastTransition, monitorTransitions, notificationResponsiveness,
                     unknownTimer);
@@ -105,23 +90,23 @@
                 mGeofenceEntries.put(geofenceId, entry);
             }
             return added;
-        });
+        }
     }
 
     @Override
     public boolean removeHardwareGeofence(int geofenceId) {
-        return runOnHandlerThread(() -> {
+        synchronized (mLock) {
             boolean removed = mNative.removeGeofence(geofenceId);
             if (removed) {
                 mGeofenceEntries.remove(geofenceId);
             }
             return removed;
-        });
+        }
     }
 
     @Override
     public boolean pauseHardwareGeofence(int geofenceId) {
-        return runOnHandlerThread(() -> {
+        synchronized (mLock) {
             boolean paused = mNative.pauseGeofence(geofenceId);
             if (paused) {
                 GeofenceEntry entry = mGeofenceEntries.get(geofenceId);
@@ -130,12 +115,12 @@
                 }
             }
             return paused;
-        });
+        }
     }
 
     @Override
     public boolean resumeHardwareGeofence(int geofenceId, int monitorTransitions) {
-        return runOnHandlerThread(() -> {
+        synchronized (mLock) {
             boolean resumed = mNative.resumeGeofence(geofenceId, monitorTransitions);
             if (resumed) {
                 GeofenceEntry entry = mGeofenceEntries.get(geofenceId);
@@ -145,7 +130,7 @@
                 }
             }
             return resumed;
-        });
+        }
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index d5e4681..330d1d5 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -762,7 +762,7 @@
                 looper, this);
         mHandler.post(mGnssSatelliteBlacklistHelper::updateSatelliteBlacklist);
         mGnssBatchingProvider = new GnssBatchingProvider();
-        mGnssGeofenceProvider = new GnssGeofenceProvider(looper);
+        mGnssGeofenceProvider = new GnssGeofenceProvider();
     }
 
     /**
@@ -1824,7 +1824,7 @@
     /**
      * Converts the GPS HAL status to the internal Geofence Hardware status.
      */
-    private int getGeofenceStatus(int status) {
+    private static int getGeofenceStatus(int status) {
         switch (status) {
             case GPS_GEOFENCE_OPERATION_SUCCESS:
                 return GeofenceHardware.GEOFENCE_SUCCESS;
@@ -1849,75 +1849,87 @@
      */
     private void reportGeofenceTransition(int geofenceId, Location location, int transition,
             long transitionTimestamp) {
-        if (mGeofenceHardwareImpl == null) {
-            mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
-        }
+        mHandler.post(() -> {
+            if (mGeofenceHardwareImpl == null) {
+                mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
+            }
 
-        mGeofenceHardwareImpl.reportGeofenceTransition(
-                geofenceId,
-                location,
-                transition,
-                transitionTimestamp,
-                GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
-                FusedBatchOptions.SourceTechnologies.GNSS);
+            mGeofenceHardwareImpl.reportGeofenceTransition(
+                    geofenceId,
+                    location,
+                    transition,
+                    transitionTimestamp,
+                    GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
+                    FusedBatchOptions.SourceTechnologies.GNSS);
+        });
     }
 
     /**
      * called from native code to report GPS status change.
      */
     private void reportGeofenceStatus(int status, Location location) {
-        if (mGeofenceHardwareImpl == null) {
-            mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
-        }
-        int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
-        if (status == GPS_GEOFENCE_AVAILABLE) {
-            monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
-        }
-        mGeofenceHardwareImpl.reportGeofenceMonitorStatus(
-                GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
-                monitorStatus,
-                location,
-                FusedBatchOptions.SourceTechnologies.GNSS);
+        mHandler.post(() -> {
+            if (mGeofenceHardwareImpl == null) {
+                mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
+            }
+            int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
+            if (status == GPS_GEOFENCE_AVAILABLE) {
+                monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
+            }
+            mGeofenceHardwareImpl.reportGeofenceMonitorStatus(
+                    GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
+                    monitorStatus,
+                    location,
+                    FusedBatchOptions.SourceTechnologies.GNSS);
+        });
     }
 
     /**
      * called from native code - Geofence Add callback
      */
     private void reportGeofenceAddStatus(int geofenceId, int status) {
-        if (mGeofenceHardwareImpl == null) {
-            mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
-        }
-        mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status));
+        mHandler.post(() -> {
+            if (mGeofenceHardwareImpl == null) {
+                mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
+            }
+            mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status));
+        });
     }
 
     /**
      * called from native code - Geofence Remove callback
      */
     private void reportGeofenceRemoveStatus(int geofenceId, int status) {
-        if (mGeofenceHardwareImpl == null) {
-            mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
-        }
-        mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status));
+        mHandler.post(() -> {
+            if (mGeofenceHardwareImpl == null) {
+                mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
+            }
+            mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status));
+        });
     }
 
     /**
      * called from native code - Geofence Pause callback
      */
     private void reportGeofencePauseStatus(int geofenceId, int status) {
-        if (mGeofenceHardwareImpl == null) {
-            mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
-        }
-        mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status));
+        mHandler.post(() -> {
+            if (mGeofenceHardwareImpl == null) {
+                mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
+            }
+            mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status));
+        });
     }
 
     /**
      * called from native code - Geofence Resume callback
      */
     private void reportGeofenceResumeStatus(int geofenceId, int status) {
-        if (mGeofenceHardwareImpl == null) {
-            mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
-        }
-        mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status));
+        mHandler.post(() -> {
+            if (mGeofenceHardwareImpl == null) {
+                mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
+            }
+            mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status));
+        });
     }
 
     //=============================================================
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
index c4f1f3d..4480435 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
@@ -24,8 +24,7 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.IStrongAuthTracker;
 import android.content.Context;
-import android.content.pm.PackageManager;
-import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.biometrics.BiometricManager;
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteCallbackList;
@@ -62,7 +61,7 @@
     private final Context mContext;
 
     private AlarmManager mAlarmManager;
-    private FingerprintManager mFingerprintManager;
+    private BiometricManager mBiometricManager;
 
     public LockSettingsStrongAuth(Context context) {
         mContext = context;
@@ -71,9 +70,8 @@
     }
 
     public void systemReady() {
-        final PackageManager pm = mContext.getPackageManager();
-        if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
-            mFingerprintManager = mContext.getSystemService(FingerprintManager.class);
+        if (BiometricManager.hasBiometrics(mContext)) {
+            mBiometricManager = mContext.getSystemService(BiometricManager.class);
         }
     }
 
@@ -187,9 +185,9 @@
     }
 
     public void reportSuccessfulStrongAuthUnlock(int userId) {
-        if (mFingerprintManager != null) {
-            byte[] token = null; /* TODO: pass real auth token once fp HAL supports it */
-            mFingerprintManager.resetTimeout(token);
+        if (mBiometricManager != null) {
+            byte[] token = null; /* TODO: pass real auth token once HAL supports it */
+            mBiometricManager.resetTimeout(token);
         }
 
         final int argNotUsed = 0;
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index d32c299..0e195bc 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -29,6 +29,7 @@
 import android.os.RemoteException;
 import android.os.UserManager;
 import android.security.GateKeeper;
+import android.security.Scrypt;
 import android.service.gatekeeper.GateKeeperResponse;
 import android.service.gatekeeper.IGateKeeperService;
 import android.util.ArrayMap;
@@ -1173,11 +1174,10 @@
     }
 
     protected byte[] scrypt(String password, byte[] salt, int N, int r, int p, int outLen) {
-        return nativeScrypt(password.getBytes(), salt, N, r, p, outLen);
+        return new Scrypt().scrypt(password.getBytes(), salt, N, r, p, outLen);
     }
 
     native long nativeSidFromPasswordHandle(byte[] handle);
-    native byte[] nativeScrypt(byte[] password, byte[] salt, int N, int r, int p, int outLen);
 
     protected static ArrayList<Byte> toByteArrayList(byte[] data) {
         ArrayList<Byte> result = new ArrayList<Byte>(data.length);
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index a16dcf3..a2e7e0c 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -352,7 +352,7 @@
 
         // Clear UID from current stats snapshot
         if (mLastSnapshot != null) {
-            mLastSnapshot = mLastSnapshot.withoutUids(uids);
+            mLastSnapshot.removeUids(uids);
         }
 
         final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 95e1962..f19ecf3 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5511,7 +5511,12 @@
     {
         mHandler.removeCallbacksAndMessages(r);
         Message m = Message.obtain(mHandler, MESSAGE_DURATION_REACHED, r);
-        long delay = r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY;
+        int delay = r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY;
+        // Accessibility users may need longer timeout duration. This api compares original delay
+        // with user's preference and return longer one. It returns original delay if there's no
+        // preference.
+        delay = mAccessibilityManager.getRecommendedTimeoutMillis(delay,
+                AccessibilityManager.FLAG_CONTENT_TEXT);
         mHandler.sendMessageDelayed(m, delay);
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index dab4e79..6bfcfa2 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8631,16 +8631,8 @@
 
         if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) {
             // The version of the application on the /system partition is less than or
-            // equal to the version on the /data partition. Even though the disabled system package
-            // is likely to be replaced by a version on the /data partition, we make assumptions
-            // that it's part of the mPackages collection during package manager initialization. So,
-            // add it to mPackages if there isn't already a package in the collection and then throw
-            // an exception to use the application already installed on the /data partition.
-            synchronized (mPackages) {
-                if (!mPackages.containsKey(pkg.packageName)) {
-                    mPackages.put(pkg.packageName, pkg);
-                }
-            }
+            // equal to the version on the /data partition. Throw an exception and use
+            // the application already installed on the /data partition.
             throw new PackageManagerException(Log.WARN, "Package " + pkg.packageName + " at "
                     + pkg.codePath + " ignored: updated version " + pkgSetting.versionCode
                     + " better than this " + pkg.getLongVersionCode());
@@ -11266,7 +11258,7 @@
                                 == UsesPermissionInfo.USAGE_UNDEFINED
                             || upi.getDataRetention() == UsesPermissionInfo.RETENTION_UNDEFINED) {
                         // STOPSHIP: Make this throw
-                        Slog.wtf(TAG, "Package " + pkg.packageName + " does not provide usage "
+                        Slog.e(TAG, "Package " + pkg.packageName + " does not provide usage "
                                 + "information for permission " + upi.getPermission()
                                 + ". This will be a fatal error in Q.");
                     }
diff --git a/services/core/java/com/android/server/role/RemoteRoleControllerService.java b/services/core/java/com/android/server/role/RemoteRoleControllerService.java
index cb89780..cc3064e 100644
--- a/services/core/java/com/android/server/role/RemoteRoleControllerService.java
+++ b/services/core/java/com/android/server/role/RemoteRoleControllerService.java
@@ -34,8 +34,8 @@
 import android.rolecontrollerservice.RoleControllerService;
 import android.util.Slog;
 
-import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.FgThread;
 
 import java.util.ArrayDeque;
 import java.util.Queue;
@@ -48,10 +48,6 @@
     static final boolean DEBUG = false;
     private static final String LOG_TAG = RemoteRoleControllerService.class.getSimpleName();
 
-    // TODO: STOPSHIP: This isn't the right thread, as we are also using it to write to disk.
-    @NonNull
-    private static final Handler sCallbackHandler = BackgroundThread.getHandler();
-
     @NonNull
     private final Connection mConnection;
 
@@ -99,8 +95,8 @@
      * @see RoleControllerService#onGrantDefaultRoles(RoleManagerCallback)
      */
     public void onGrantDefaultRoles(@NonNull IRoleManagerCallback callback) {
-        mConnection.enqueueCall(
-                new Connection.Call(IRoleControllerService::onGrantDefaultRoles, callback));
+        mConnection.enqueueCall(new Connection.Call(IRoleControllerService::onGrantDefaultRoles,
+                callback));
     }
 
     private static final class Connection implements ServiceConnection {
@@ -113,6 +109,9 @@
         @NonNull
         private final Context mContext;
 
+        @NonNull
+        private final Handler mHandler = FgThread.getHandler();
+
         private boolean mBound;
 
         @Nullable
@@ -161,8 +160,8 @@
             if (DEBUG) {
                 Slog.i(LOG_TAG, "Enqueue " + call);
             }
-            sCallbackHandler.executeOrSendMessage(PooledLambda.obtainMessage(
-                    Connection::executeCall, this, call));
+            mHandler.executeOrSendMessage(PooledLambda.obtainMessage(Connection::executeCall, this,
+                    call));
         }
 
         @WorkerThread
@@ -181,7 +180,7 @@
 
         @WorkerThread
         private void ensureBound() {
-            sCallbackHandler.removeCallbacks(mUnbindRunnable);
+            mHandler.removeCallbacks(mUnbindRunnable);
             if (!mBound) {
                 Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
                 intent.setPackage(mContext.getPackageManager()
@@ -191,13 +190,13 @@
                 //
                 // Note that as a result, onServiceConnected may happen not on main thread!
                 mBound = mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE,
-                        sCallbackHandler, UserHandle.of(mUserId));
+                        mHandler, UserHandle.of(mUserId));
             }
         }
 
         private void scheduleUnbind() {
-            sCallbackHandler.removeCallbacks(mUnbindRunnable);
-            sCallbackHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS);
+            mHandler.removeCallbacks(mUnbindRunnable);
+            mHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS);
         }
 
         @WorkerThread
@@ -220,6 +219,9 @@
             private final IRoleManagerCallback mCallback;
 
             @NonNull
+            private final Handler mHandler = FgThread.getHandler();
+
+            @NonNull
             private final Runnable mTimeoutRunnable = this::notifyTimeout;
 
             private boolean mCallbackNotified;
@@ -236,7 +238,7 @@
                     Slog.i(LOG_TAG, "Executing " + this);
                 }
                 try {
-                    sCallbackHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS);
+                    mHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS);
                     mCallExecutor.execute(service, new CallbackDelegate());
                 } catch (RemoteException e) {
                     Slog.e(LOG_TAG, "Error calling RoleControllerService", e);
@@ -256,7 +258,7 @@
                     return;
                 }
                 mCallbackNotified = true;
-                sCallbackHandler.removeCallbacks(mTimeoutRunnable);
+                mHandler.removeCallbacks(mTimeoutRunnable);
                 try {
                     if (success) {
                         mCallback.onSuccess();
@@ -286,14 +288,14 @@
 
                 @Override
                 public void onSuccess() throws RemoteException {
-                    sCallbackHandler.sendMessage(PooledLambda.obtainMessage(
-                            Call::notifyCallback, Call.this, true));
+                    mHandler.sendMessage(PooledLambda.obtainMessage(Call::notifyCallback, Call.this,
+                            true));
                 }
 
                 @Override
                 public void onFailure() throws RemoteException {
-                    sCallbackHandler.sendMessage(PooledLambda.obtainMessage(
-                            Call::notifyCallback, Call.this, false));
+                    mHandler.sendMessage(PooledLambda.obtainMessage(Call::notifyCallback, Call.this,
+                            false));
                 }
             }
         }
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index d5faab5..8711ddf 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -42,17 +42,23 @@
 import android.util.PackageUtils;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.BitUtils;
 import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FunctionalUtils;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.dump.DualDumpOutputStream;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 
 import java.io.ByteArrayOutputStream;
 import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -150,21 +156,16 @@
     @MainThread
     private void performInitialGrantsIfNecessary(@UserIdInt int userId) {
         RoleUserState userState;
-        synchronized (mLock) {
-            userState = getUserStateLocked(userId);
-        }
+        userState = getOrCreateUserState(userId);
         String packagesHash = computeComponentStateHash(userId);
-        String lastGrantPackagesHash;
-        synchronized (mLock) {
-            lastGrantPackagesHash = userState.getLastGrantPackagesHashLocked();
-        }
-        boolean needGrant = !Objects.equals(packagesHash, lastGrantPackagesHash);
+        String oldPackagesHash = userState.getPackagesHash();
+        boolean needGrant = !Objects.equals(packagesHash, oldPackagesHash);
         if (needGrant) {
             // Some vital packages state has changed since last role grant
             // Run grants again
             Slog.i(LOG_TAG, "Granting default permissions...");
             CompletableFuture<Void> result = new CompletableFuture<>();
-            getControllerService(userId).onGrantDefaultRoles(
+            getOrCreateControllerService(userId).onGrantDefaultRoles(
                     new IRoleManagerCallback.Stub() {
                         @Override
                         public void onSuccess() {
@@ -177,9 +178,7 @@
                     });
             try {
                 result.get(5, TimeUnit.SECONDS);
-                synchronized (mLock) {
-                    userState.setLastGrantPackagesHashLocked(packagesHash);
-                }
+                userState.setPackagesHash(packagesHash);
             } catch (InterruptedException | ExecutionException | TimeoutException e) {
                 Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e);
             }
@@ -219,35 +218,38 @@
         return PackageUtils.computeSha256Digest(out.toByteArray());
     }
 
-    @GuardedBy("mLock")
     @NonNull
-    private RoleUserState getUserStateLocked(@UserIdInt int userId) {
-        RoleUserState userState = mUserStates.get(userId);
-        if (userState == null) {
-            userState = RoleUserState.newInstanceLocked(userId);
-            mUserStates.put(userId, userState);
+    private RoleUserState getOrCreateUserState(@UserIdInt int userId) {
+        synchronized (mLock) {
+            RoleUserState userState = mUserStates.get(userId);
+            if (userState == null) {
+                userState = new RoleUserState(userId);
+                mUserStates.put(userId, userState);
+            }
+            return userState;
         }
-        return userState;
     }
 
-    @GuardedBy("mLock")
     @NonNull
-    private RemoteRoleControllerService getControllerService(@UserIdInt int userId) {
-        RemoteRoleControllerService controllerService = mControllerServices.get(userId);
-        if (controllerService == null) {
-            controllerService = new RemoteRoleControllerService(userId, getContext());
-            mControllerServices.put(userId, controllerService);
+    private RemoteRoleControllerService getOrCreateControllerService(@UserIdInt int userId) {
+        synchronized (mLock) {
+            RemoteRoleControllerService controllerService = mControllerServices.get(userId);
+            if (controllerService == null) {
+                controllerService = new RemoteRoleControllerService(userId, getContext());
+                mControllerServices.put(userId, controllerService);
+            }
+            return controllerService;
         }
-        return controllerService;
     }
 
     private void onRemoveUser(@UserIdInt int userId) {
+        RoleUserState userState;
         synchronized (mLock) {
             mControllerServices.remove(userId);
-            RoleUserState userState = mUserStates.removeReturnOld(userId);
-            if (userState != null) {
-                userState.destroySyncLocked();
-            }
+            userState = mUserStates.removeReturnOld(userId);
+        }
+        if (userState != null) {
+            userState.destroy();
         }
     }
 
@@ -258,10 +260,8 @@
             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
 
             int userId = UserHandle.getUserId(getCallingUid());
-            synchronized (mLock) {
-                RoleUserState userState = getUserStateLocked(userId);
-                return userState.isRoleAvailableLocked(roleName);
-            }
+            RoleUserState userState = getOrCreateUserState(userId);
+            return userState.isRoleAvailable(roleName);
         }
 
         @Override
@@ -301,10 +301,8 @@
         @Nullable
         private ArraySet<String> getRoleHoldersInternal(@NonNull String roleName,
                 @UserIdInt int userId) {
-            synchronized (mLock) {
-                RoleUserState userState = getUserStateLocked(userId);
-                return userState.getRoleHoldersLocked(roleName);
-            }
+            RoleUserState userState = getOrCreateUserState(userId);
+            return userState.getRoleHolders(roleName);
         }
 
         @Override
@@ -321,7 +319,7 @@
             getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
                     "addRoleHolderAsUser");
 
-            getControllerService(userId).onAddRoleHolder(roleName, packageName, callback);
+            getOrCreateControllerService(userId).onAddRoleHolder(roleName, packageName, callback);
         }
 
         @Override
@@ -338,7 +336,7 @@
             getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
                     "removeRoleHolderAsUser");
 
-            getControllerService(userId).onRemoveRoleHolder(roleName, packageName,
+            getOrCreateControllerService(userId).onRemoveRoleHolder(roleName, packageName,
                     callback);
         }
 
@@ -355,7 +353,7 @@
             getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
                     "clearRoleHoldersAsUser");
 
-            getControllerService(userId).onClearRoleHolders(roleName, callback);
+            getOrCreateControllerService(userId).onClearRoleHolders(roleName, callback);
         }
 
         @Override
@@ -366,10 +364,8 @@
                     "setRoleNamesFromController");
 
             int userId = UserHandle.getCallingUserId();
-            synchronized (mLock) {
-                RoleUserState userState = getUserStateLocked(userId);
-                userState.setRoleNamesLocked(roleNames);
-            }
+            RoleUserState userState = getOrCreateUserState(userId);
+            userState.setRoleNames(roleNames);
         }
 
         @Override
@@ -382,10 +378,8 @@
                     "addRoleHolderFromController");
 
             int userId = UserHandle.getCallingUserId();
-            synchronized (mLock) {
-                RoleUserState userState = getUserStateLocked(userId);
-                return userState.addRoleHolderLocked(roleName, packageName);
-            }
+            RoleUserState userState = getOrCreateUserState(userId);
+            return userState.addRoleHolder(roleName, packageName);
         }
 
         @Override
@@ -398,10 +392,8 @@
                     "removeRoleHolderFromController");
 
             int userId = UserHandle.getCallingUserId();
-            synchronized (mLock) {
-                RoleUserState userState = getUserStateLocked(userId);
-                return userState.removeRoleHolderLocked(roleName, packageName);
-            }
+            RoleUserState userState = getOrCreateUserState(userId);
+            return userState.removeRoleHolder(roleName, packageName);
         }
 
         @CheckResult
@@ -417,5 +409,34 @@
             new RoleManagerShellCommand(this).exec(this, in, out, err, args, callback,
                     resultReceiver);
         }
+
+        @Override
+        protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
+                @Nullable String[] args) {
+            if (!DumpUtils.checkDumpPermission(getContext(), LOG_TAG, fout)) {
+                return;
+            }
+
+            boolean dumpAsProto = args != null && ArrayUtils.contains(args, "--proto");
+            DualDumpOutputStream dumpOutputStream;
+            if (dumpAsProto) {
+                dumpOutputStream = new DualDumpOutputStream(new ProtoOutputStream(fd));
+            } else {
+                fout.println("ROLE MANAGER STATE (dumpsys role):");
+                dumpOutputStream = new DualDumpOutputStream(new IndentingPrintWriter(fout, "  "));
+            }
+
+            int[] userIds = mUserManagerInternal.getUserIds();
+            int userIdsLength = userIds.length;
+            for (int i = 0; i < userIdsLength; i++) {
+                int userId = userIds[i];
+
+                RoleUserState userState = getOrCreateUserState(userId);
+                userState.dump(dumpOutputStream, "user_states",
+                        RoleManagerServiceDumpProto.USER_STATES);
+            }
+
+            dumpOutputStream.flush();
+        }
     }
 }
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
index 3e3e156..ec614a4 100644
--- a/services/core/java/com/android/server/role/RoleUserState.java
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -32,6 +32,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.dump.DualDumpOutputStream;
 import com.android.internal.util.function.pooled.PooledLambda;
 
 import libcore.io.IoUtils;
@@ -60,6 +61,8 @@
 
     private static final String ROLES_FILE_NAME = "roles.xml";
 
+    private static final long WRITE_DELAY_MILLIS = 200;
+
     private static final String TAG_ROLES = "roles";
     private static final String TAG_ROLE = "role";
     private static final String TAG_HOLDER = "holder";
@@ -70,51 +73,51 @@
     @UserIdInt
     private final int mUserId;
 
-    @GuardedBy("RoleManagerService.mLock")
+    @NonNull
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
     private int mVersion = VERSION_UNDEFINED;
 
-    @GuardedBy("RoleManagerService.mLock")
+    @GuardedBy("mLock")
     @Nullable
-    private String mLastGrantPackagesHash;
+    private String mPackagesHash;
 
     /**
      * Maps role names to its holders' package names. The values should never be null.
      */
-    @GuardedBy("RoleManagerService.mLock")
+    @GuardedBy("mLock")
     @NonNull
     private ArrayMap<String, ArraySet<String>> mRoles = new ArrayMap<>();
 
-    @GuardedBy("RoleManagerService.mLock")
+    @GuardedBy("mLock")
+    private boolean mWriteScheduled;
+
+    @GuardedBy("mLock")
     private boolean mDestroyed;
 
     @NonNull
     private final Handler mWriteHandler = new Handler(BackgroundThread.getHandler().getLooper());
 
-    private RoleUserState(@UserIdInt int userId) {
-        mUserId = userId;
-
-        readSyncLocked();
-    }
-
     /**
      * Create a new instance of user state, and read its state from disk if previously persisted.
      *
      * @param userId the user id for the new user state
-     *
-     * @return the new user state
      */
-    @GuardedBy("RoleManagerService.mLock")
-    public static RoleUserState newInstanceLocked(@UserIdInt int userId) {
-        return new RoleUserState(userId);
+    public RoleUserState(@UserIdInt int userId) {
+        mUserId = userId;
+
+        readFile();
     }
 
     /**
      * Get the version of this user state.
      */
-    @GuardedBy("RoleManagerService.mLock")
-    public int getVersionLocked() {
-        throwIfDestroyedLocked();
-        return mVersion;
+    public int getVersion() {
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            return mVersion;
+        }
     }
 
     /**
@@ -122,14 +125,15 @@
      *
      * @param version the version to set
      */
-    @GuardedBy("RoleManagerService.mLock")
-    public void setVersionLocked(int version) {
-        throwIfDestroyedLocked();
-        if (mVersion == version) {
-            return;
+    public void setVersion(int version) {
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            if (mVersion == version) {
+                return;
+            }
+            mVersion = version;
+            scheduleWriteFileLocked();
         }
-        mVersion = version;
-        writeAsyncLocked();
     }
 
     /**
@@ -137,24 +141,27 @@
      *
      * @return the hash representing the state of packages
      */
-    @GuardedBy("RoleManagerService.mLock")
-    public String getLastGrantPackagesHashLocked() {
-        return mLastGrantPackagesHash;
+    @Nullable
+    public String getPackagesHash() {
+        synchronized (mLock) {
+            return mPackagesHash;
+        }
     }
 
     /**
      * Set the hash representing the state of packages during the last time initial grants was run.
      *
-     * @param lastGrantPackagesHash the hash representing the state of packages
+     * @param packagesHash the hash representing the state of packages
      */
-    @GuardedBy("RoleManagerService.mLock")
-    public void setLastGrantPackagesHashLocked(@Nullable String lastGrantPackagesHash) {
-        throwIfDestroyedLocked();
-        if (Objects.equals(mLastGrantPackagesHash, lastGrantPackagesHash)) {
-            return;
+    public void setPackagesHash(@Nullable String packagesHash) {
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            if (Objects.equals(mPackagesHash, packagesHash)) {
+                return;
+            }
+            mPackagesHash = packagesHash;
+            scheduleWriteFileLocked();
         }
-        mLastGrantPackagesHash = lastGrantPackagesHash;
-        writeAsyncLocked();
     }
 
     /**
@@ -164,10 +171,11 @@
      *
      * @return whether the role is available
      */
-    @GuardedBy("RoleManagerService.mLock")
-    public boolean isRoleAvailableLocked(@NonNull String roleName) {
-        throwIfDestroyedLocked();
-        return mRoles.containsKey(roleName);
+    public boolean isRoleAvailable(@NonNull String roleName) {
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            return mRoles.containsKey(roleName);
+        }
     }
 
     /**
@@ -177,11 +185,12 @@
      *
      * @return the set of role holders. {@code null} should not be returned and indicates an issue.
      */
-    @GuardedBy("RoleManagerService.mLock")
     @Nullable
-    public ArraySet<String> getRoleHoldersLocked(@NonNull String roleName) {
-        throwIfDestroyedLocked();
-        return mRoles.get(roleName);
+    public ArraySet<String> getRoleHolders(@NonNull String roleName) {
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            return new ArraySet<>(mRoles.get(roleName));
+        }
     }
 
     /**
@@ -189,33 +198,35 @@
      *
      * @param roleNames the names of all the available roles
      */
-    @GuardedBy("RoleManagerService.mLock")
-    public void setRoleNamesLocked(@NonNull List<String> roleNames) {
-        throwIfDestroyedLocked();
-        boolean changed = false;
-        for (int i = mRoles.size() - 1; i >= 0; i--) {
-            String roleName = mRoles.keyAt(i);
-            if (!roleNames.contains(roleName)) {
-                ArraySet<String> packageNames = mRoles.valueAt(i);
-                if (!packageNames.isEmpty()) {
-                    Slog.e(LOG_TAG, "Holders of a removed role should have been cleaned up, role: "
-                            + roleName + ", holders: " + packageNames);
+    public void setRoleNames(@NonNull List<String> roleNames) {
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            boolean changed = false;
+            for (int i = mRoles.size() - 1; i >= 0; i--) {
+                String roleName = mRoles.keyAt(i);
+                if (!roleNames.contains(roleName)) {
+                    ArraySet<String> packageNames = mRoles.valueAt(i);
+                    if (!packageNames.isEmpty()) {
+                        Slog.e(LOG_TAG,
+                                "Holders of a removed role should have been cleaned up, role: "
+                                        + roleName + ", holders: " + packageNames);
+                    }
+                    mRoles.removeAt(i);
+                    changed = true;
                 }
-                mRoles.removeAt(i);
-                changed = true;
             }
-        }
-        int roleNamesSize = roleNames.size();
-        for (int i = 0; i < roleNamesSize; i++) {
-            String roleName = roleNames.get(i);
-            if (!mRoles.containsKey(roleName)) {
-                mRoles.put(roleName, new ArraySet<>());
-                Slog.i(LOG_TAG, "Added new role: " + roleName);
-                changed = true;
+            int roleNamesSize = roleNames.size();
+            for (int i = 0; i < roleNamesSize; i++) {
+                String roleName = roleNames.get(i);
+                if (!mRoles.containsKey(roleName)) {
+                    mRoles.put(roleName, new ArraySet<>());
+                    Slog.i(LOG_TAG, "Added new role: " + roleName);
+                    changed = true;
+                }
             }
-        }
-        if (changed) {
-            writeAsyncLocked();
+            if (changed) {
+                scheduleWriteFileLocked();
+            }
         }
     }
 
@@ -229,20 +240,21 @@
      *         indicates an issue.
      */
     @CheckResult
-    @GuardedBy("RoleManagerService.mLock")
-    public boolean addRoleHolderLocked(@NonNull String roleName, @NonNull String packageName) {
-        throwIfDestroyedLocked();
-        ArraySet<String> roleHolders = mRoles.get(roleName);
-        if (roleHolders == null) {
-            Slog.e(LOG_TAG, "Cannot add role holder for unknown role, role: " + roleName
-                    + ", package: " + packageName);
-            return false;
+    public boolean addRoleHolder(@NonNull String roleName, @NonNull String packageName) {
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            ArraySet<String> roleHolders = mRoles.get(roleName);
+            if (roleHolders == null) {
+                Slog.e(LOG_TAG, "Cannot add role holder for unknown role, role: " + roleName
+                        + ", package: " + packageName);
+                return false;
+            }
+            boolean changed = roleHolders.add(packageName);
+            if (changed) {
+                scheduleWriteFileLocked();
+            }
+            return true;
         }
-        boolean changed = roleHolders.add(packageName);
-        if (changed) {
-            writeAsyncLocked();
-        }
-        return true;
     }
 
     /**
@@ -255,46 +267,54 @@
      *         indicates an issue.
      */
     @CheckResult
-    @GuardedBy("RoleManagerService.mLock")
-    public boolean removeRoleHolderLocked(@NonNull String roleName, @NonNull String packageName) {
-        throwIfDestroyedLocked();
-        ArraySet<String> roleHolders = mRoles.get(roleName);
-        if (roleHolders == null) {
-            Slog.e(LOG_TAG, "Cannot remove role holder for unknown role, role: " + roleName
-                    + ", package: " + packageName);
-            return false;
+    public boolean removeRoleHolder(@NonNull String roleName, @NonNull String packageName) {
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            ArraySet<String> roleHolders = mRoles.get(roleName);
+            if (roleHolders == null) {
+                Slog.e(LOG_TAG, "Cannot remove role holder for unknown role, role: " + roleName
+                        + ", package: " + packageName);
+                return false;
+            }
+            boolean changed = roleHolders.remove(packageName);
+            if (changed) {
+                scheduleWriteFileLocked();
+            }
+            return true;
         }
-        boolean changed = roleHolders.remove(packageName);
-        if (changed) {
-            writeAsyncLocked();
-        }
-        return true;
     }
 
     /**
      * Schedule writing the state to file.
      */
-    @GuardedBy("RoleManagerService.mLock")
-    private void writeAsyncLocked() {
+    @GuardedBy("mLock")
+    private void scheduleWriteFileLocked() {
         throwIfDestroyedLocked();
 
-        ArrayMap<String, ArraySet<String>> roles = new ArrayMap<>();
-        for (int i = 0, size = CollectionUtils.size(mRoles); i < size; ++i) {
-            String roleName = mRoles.keyAt(i);
-            ArraySet<String> roleHolders = mRoles.valueAt(i);
-            roleHolders = new ArraySet<>(roleHolders);
-            roles.put(roleName, roleHolders);
+        if (!mWriteScheduled) {
+            mWriteHandler.sendMessageDelayed(PooledLambda.obtainMessage(RoleUserState::writeFile,
+                    this), WRITE_DELAY_MILLIS);
+            mWriteScheduled = true;
         }
-
-        mWriteHandler.removeCallbacksAndMessages(null);
-        // TODO: Throttle writes.
-        mWriteHandler.sendMessage(PooledLambda.obtainMessage(RoleUserState::writeSync, this,
-                mVersion, mLastGrantPackagesHash, roles));
     }
 
     @WorkerThread
-    private void writeSync(int version, @Nullable String packagesHash,
-            @NonNull ArrayMap<String, ArraySet<String>> roles) {
+    private void writeFile() {
+        int version;
+        String packagesHash;
+        ArrayMap<String, ArraySet<String>> roles;
+        synchronized (mLock) {
+            if (mDestroyed) {
+                return;
+            }
+
+            mWriteScheduled = false;
+
+            version = mVersion;
+            packagesHash = mPackagesHash;
+            roles = snapshotRolesLocked();
+        }
+
         AtomicFile atomicFile = new AtomicFile(getFile(mUserId), "roles-" + mUserId);
         FileOutputStream out = null;
         try {
@@ -310,6 +330,7 @@
 
             serializer.endDocument();
             atomicFile.finishWrite(out);
+            Slog.i(LOG_TAG, "Wrote roles.xml successfully");
         } catch (IllegalArgumentException | IllegalStateException | IOException e) {
             Slog.wtf(LOG_TAG, "Failed to write roles.xml, restoring backup", e);
             if (out != null) {
@@ -360,17 +381,19 @@
     /**
      * Read the state from file.
      */
-    @GuardedBy("RoleManagerService.mLock")
-    private void readSyncLocked() {
-        File file = getFile(mUserId);
-        try (FileInputStream in = new AtomicFile(file).openRead()) {
-            XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(in, null);
-            parseXmlLocked(parser);
-        } catch (FileNotFoundException e) {
-            Slog.i(LOG_TAG, "roles.xml not found");
-        } catch (XmlPullParserException | IOException e) {
-            throw new IllegalStateException("Failed to parse roles.xml: " + file, e);
+    private void readFile() {
+        synchronized (mLock) {
+            File file = getFile(mUserId);
+            try (FileInputStream in = new AtomicFile(file).openRead()) {
+                XmlPullParser parser = Xml.newPullParser();
+                parser.setInput(in, null);
+                parseXmlLocked(parser);
+                Slog.i(LOG_TAG, "Read roles.xml successfully");
+            } catch (FileNotFoundException e) {
+                Slog.i(LOG_TAG, "roles.xml not found");
+            } catch (XmlPullParserException | IOException e) {
+                throw new IllegalStateException("Failed to parse roles.xml: " + file, e);
+            }
         }
     }
 
@@ -396,7 +419,7 @@
     private void parseRolesLocked(@NonNull XmlPullParser parser) throws IOException,
             XmlPullParserException {
         mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_VERSION));
-        mLastGrantPackagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
+        mPackagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
         mRoles.clear();
 
         int type;
@@ -440,18 +463,76 @@
     }
 
     /**
+     * Dump this user state.
+     *
+     * @param dumpOutputStream the output stream to dump to
+     */
+    public void dump(@NonNull DualDumpOutputStream dumpOutputStream, @NonNull String fieldName,
+            long fieldId) {
+        int version;
+        String packagesHash;
+        ArrayMap<String, ArraySet<String>> roles;
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+
+            version = mVersion;
+            packagesHash = mPackagesHash;
+            roles = snapshotRolesLocked();
+        }
+
+        long fieldToken = dumpOutputStream.start(fieldName, fieldId);
+        dumpOutputStream.write("user_id", RoleUserStateProto.USER_ID, mUserId);
+        dumpOutputStream.write("version", RoleUserStateProto.VERSION, version);
+        dumpOutputStream.write("packages_hash", RoleUserStateProto.PACKAGES_HASH, packagesHash);
+
+        int rolesSize = roles.size();
+        for (int rolesIndex = 0; rolesIndex < rolesSize; rolesIndex++) {
+            String roleName = roles.keyAt(rolesIndex);
+            ArraySet<String> roleHolders = roles.valueAt(rolesIndex);
+
+            long rolesToken = dumpOutputStream.start("roles", RoleUserStateProto.ROLES);
+            dumpOutputStream.write("name", RoleProto.NAME, roleName);
+
+            int roleHoldersSize = roleHolders.size();
+            for (int roleHoldersIndex = 0; roleHoldersIndex < roleHoldersSize; roleHoldersIndex++) {
+                String roleHolder = roleHolders.valueAt(roleHoldersIndex);
+
+                dumpOutputStream.write("holders", RoleProto.HOLDERS, roleHolder);
+            }
+
+            dumpOutputStream.end(rolesToken);
+        }
+
+        dumpOutputStream.end(fieldToken);
+    }
+
+    @GuardedBy("mLock")
+    private ArrayMap<String, ArraySet<String>> snapshotRolesLocked() {
+        ArrayMap<String, ArraySet<String>> roles = new ArrayMap<>();
+        for (int i = 0, size = CollectionUtils.size(mRoles); i < size; ++i) {
+            String roleName = mRoles.keyAt(i);
+            ArraySet<String> roleHolders = mRoles.valueAt(i);
+
+            roleHolders = new ArraySet<>(roleHolders);
+            roles.put(roleName, roleHolders);
+        }
+        return roles;
+    }
+
+    /**
      * Destroy this state and delete the corresponding file. Any pending writes to the file will be
      * cancelled and any future interaction with this state will throw an exception.
      */
-    @GuardedBy("RoleManagerService.mLock")
-    public void destroySyncLocked() {
-        throwIfDestroyedLocked();
-        mWriteHandler.removeCallbacksAndMessages(null);
-        getFile(mUserId).delete();
-        mDestroyed = true;
+    public void destroy() {
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            mWriteHandler.removeCallbacksAndMessages(null);
+            getFile(mUserId).delete();
+            mDestroyed = true;
+        }
     }
 
-    @GuardedBy("RoleManagerService.mLock")
+    @GuardedBy("mLock")
     private void throwIfDestroyedLocked() {
         if (mDestroyed) {
             throw new IllegalStateException("This RoleUserState has already been destroyed");
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.aidl b/services/core/java/com/android/server/signedconfig/InvalidConfigException.java
similarity index 61%
copy from core/java/android/view/intelligence/ContentCaptureEvent.aidl
copy to services/core/java/com/android/server/signedconfig/InvalidConfigException.java
index c66a6cb..f01baa4 100644
--- a/core/java/android/view/intelligence/ContentCaptureEvent.aidl
+++ b/services/core/java/com/android/server/signedconfig/InvalidConfigException.java
@@ -14,6 +14,20 @@
  * limitations under the License.
  */
 
-package android.view.intelligence;
+package com.android.server.signedconfig;
 
-parcelable ContentCaptureEvent;
+/**
+ * Thrown when there is a problem parsing the config embedded in an APK.
+ */
+public class InvalidConfigException extends Exception {
+
+    public InvalidConfigException(String message) {
+        super(message);
+    }
+
+    public InvalidConfigException(String message, Exception cause) {
+        super(message, cause);
+    }
+
+
+}
diff --git a/services/core/java/com/android/server/signedconfig/SignedConfig.java b/services/core/java/com/android/server/signedconfig/SignedConfig.java
new file mode 100644
index 0000000..a3f452c
--- /dev/null
+++ b/services/core/java/com/android/server/signedconfig/SignedConfig.java
@@ -0,0 +1,137 @@
+/*
+ * 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.server.signedconfig;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Represents signed configuration.
+ *
+ * <p>This configuration should only be used if the signature has already been verified.
+ */
+public class SignedConfig {
+
+    private static final String KEY_VERSION = "version";
+    private static final String KEY_CONFIG = "config";
+
+    private static final String CONFIG_KEY_MIN_SDK = "minSdk";
+    private static final String CONFIG_KEY_MAX_SDK = "maxSdk";
+    private static final String CONFIG_KEY_VALUES = "values";
+    // TODO it may be better to use regular key/value pairs in a JSON object, rather than an array
+    // of objects with the 2 keys below.
+    private static final String CONFIG_KEY_KEY = "key";
+    private static final String CONFIG_KEY_VALUE = "value";
+
+    /**
+     * Represents config values targetting to an SDK range.
+     */
+    public static class PerSdkConfig {
+        public final int minSdk;
+        public final int maxSdk;
+        public final Map<String, String> values;
+
+        public PerSdkConfig(int minSdk, int maxSdk, Map<String, String> values) {
+            this.minSdk = minSdk;
+            this.maxSdk = maxSdk;
+            this.values = Collections.unmodifiableMap(values);
+        }
+
+    }
+
+    public final int version;
+    public final List<PerSdkConfig> perSdkConfig;
+
+    public SignedConfig(int version, List<PerSdkConfig> perSdkConfig) {
+        this.version = version;
+        this.perSdkConfig = Collections.unmodifiableList(perSdkConfig);
+    }
+
+    /**
+     * Find matching sdk config for a given SDK level.
+     *
+     * @param sdkVersion SDK version of device.
+     * @return Matching config, of {@code null} if there is none.
+     */
+    public PerSdkConfig getMatchingConfig(int sdkVersion) {
+        for (PerSdkConfig config : perSdkConfig) {
+            if (config.minSdk <= sdkVersion && sdkVersion <= config.maxSdk) {
+                return config;
+            }
+        }
+        // nothing matching
+        return null;
+    }
+
+    /**
+     * Parse configuration from an APK.
+     *
+     * @param config config as read from the APK metadata.
+     * @return Parsed configuration.
+     * @throws InvalidConfigException If there's a problem parsing the config.
+     */
+    public static SignedConfig parse(String config, Set<String> allowedKeys)
+            throws InvalidConfigException {
+        try {
+            JSONObject json = new JSONObject(config);
+            int version = json.getInt(KEY_VERSION);
+
+            JSONArray perSdkConfig = json.getJSONArray(KEY_CONFIG);
+            List<PerSdkConfig> parsedConfigs = new ArrayList<>();
+            for (int i = 0; i < perSdkConfig.length(); ++i) {
+                parsedConfigs.add(parsePerSdkConfig(perSdkConfig.getJSONObject(i), allowedKeys));
+            }
+
+            return new SignedConfig(version, parsedConfigs);
+        } catch (JSONException e) {
+            throw new InvalidConfigException("Could not parse JSON", e);
+        }
+
+    }
+
+    @VisibleForTesting
+    static PerSdkConfig parsePerSdkConfig(JSONObject json, Set<String> allowedKeys)
+            throws JSONException, InvalidConfigException {
+        int minSdk = json.getInt(CONFIG_KEY_MIN_SDK);
+        int maxSdk = json.getInt(CONFIG_KEY_MAX_SDK);
+        JSONArray valueArray = json.getJSONArray(CONFIG_KEY_VALUES);
+        Map<String, String> values = new HashMap<>();
+        for (int i = 0; i < valueArray.length(); ++i) {
+            JSONObject keyValuePair = valueArray.getJSONObject(i);
+            String key = keyValuePair.getString(CONFIG_KEY_KEY);
+            String value = keyValuePair.has(CONFIG_KEY_VALUE)
+                    ? keyValuePair.getString(CONFIG_KEY_VALUE)
+                    : null;
+            if (!allowedKeys.contains(key)) {
+                throw new InvalidConfigException("Config key " + key + " is not allowed");
+            }
+            values.put(key, value);
+        }
+        return new PerSdkConfig(minSdk, maxSdk, values);
+    }
+
+}
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 7bf2c94..10542d5 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -48,12 +48,16 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.RootActivityContainer.FindTaskResult;
 import static com.android.server.wm.RootActivityContainer.TAG_STATES;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
 
 import android.annotation.Nullable;
 import android.app.ActivityOptions;
 import android.app.WindowConfiguration;
 import android.content.res.Configuration;
 import android.graphics.Point;
+import android.os.IBinder;
 import android.os.UserHandle;
 import android.util.IntArray;
 import android.util.Slog;
@@ -86,6 +90,8 @@
 
     private ActivityTaskManagerService mService;
     private RootActivityContainer mRootActivityContainer;
+    // TODO: Remove once unification is complete.
+    DisplayContent mDisplayContent;
     /** Actual Display this object tracks. */
     int mDisplayId;
     Display mDisplay;
@@ -138,8 +144,6 @@
     // Used in updating the display size
     private Point mTmpDisplaySize = new Point();
 
-    private DisplayWindowController mWindowContainerController;
-
     private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
 
     ActivityDisplay(RootActivityContainer root, Display display) {
@@ -147,19 +151,15 @@
         mService = root.mService;
         mDisplayId = display.getDisplayId();
         mDisplay = display;
-        mWindowContainerController = createWindowContainerController();
+        mDisplayContent = createDisplayContent();
         updateBounds();
     }
 
-    protected DisplayWindowController createWindowContainerController() {
-        return new DisplayWindowController(mDisplay, this);
+    protected DisplayContent createDisplayContent() {
+        return mService.mWindowManager.mRoot.createDisplayContent(mDisplay, this);
     }
 
-    DisplayWindowController getWindowContainerController() {
-        return mWindowContainerController;
-    }
-
-    void updateBounds() {
+    private void updateBounds() {
         mDisplay.getRealSize(mTmpDisplaySize);
         setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
     }
@@ -178,12 +178,15 @@
         }
 
         updateBounds();
-        mWindowContainerController.onDisplayChanged();
+        if (mDisplayContent != null) {
+            mDisplayContent.updateDisplayInfo();
+            mService.mWindowManager.requestTraversal();
+        }
     }
 
     @Override
     public void onInitializeOverrideConfiguration(Configuration config) {
-        getOverrideConfiguration().updateFrom(config);
+        getRequestedOverrideConfiguration().updateFrom(config);
     }
 
     void addChild(ActivityStack stack, int position) {
@@ -270,9 +273,9 @@
         // ActivityStack#getWindowContainerController() can be null. In this special case,
         // since DisplayContest#positionStackAt() is called in TaskStack#onConfigurationChanged(),
         // we don't have to call WindowContainerController#positionChildAt() here.
-        if (stack.getWindowContainerController() != null) {
-            mWindowContainerController.positionChildAt(stack.getWindowContainerController(),
-                    insertPosition, includingParents);
+        if (stack.getWindowContainerController() != null && mDisplayContent != null) {
+            mDisplayContent.positionStackAt(insertPosition,
+                    stack.getWindowContainerController().mContainer, includingParents);
         }
         if (!wasContained) {
             stack.setParent(this);
@@ -953,21 +956,28 @@
     }
 
     @Override
-    public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
-        final int currRotation = getOverrideConfiguration().windowConfiguration.getRotation();
+    public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
+        final int currRotation =
+                getRequestedOverrideConfiguration().windowConfiguration.getRotation();
         if (currRotation != ROTATION_UNDEFINED
                 && currRotation != overrideConfiguration.windowConfiguration.getRotation()
-                && getWindowContainerController() != null) {
-            getWindowContainerController().applyRotation(currRotation,
+                && mDisplayContent != null) {
+            mDisplayContent.applyRotationLocked(currRotation,
                     overrideConfiguration.windowConfiguration.getRotation());
         }
-        super.onOverrideConfigurationChanged(overrideConfiguration);
+        super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
+        if (mDisplayContent != null) {
+            mService.mWindowManager.setNewDisplayOverrideConfiguration(
+                    overrideConfiguration, mDisplayContent);
+        }
     }
 
     @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
         // update resources before cascade so that docked/pinned stacks use the correct info
-        getWindowContainerController().preOnConfigurationChanged();
+        if (mDisplayContent != null) {
+            mDisplayContent.preOnConfigurationChanged();
+        }
         super.onConfigurationChanged(newParentConfig);
     }
 
@@ -1098,8 +1108,8 @@
 
     private void releaseSelfIfNeeded() {
         if (mStacks.isEmpty() && mRemoved) {
-            mWindowContainerController.removeContainer();
-            mWindowContainerController = null;
+            mDisplayContent.removeIfPossible();
+            mDisplayContent = null;
             mRootActivityContainer.removeChild(this);
             mRootActivityContainer.mStackSupervisor
                     .getKeyguardController().onDisplayRemoved(mDisplayId);
@@ -1121,7 +1131,7 @@
      * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
      */
     boolean supportsSystemDecorations() {
-        return mWindowContainerController.supportsSystemDecorations();
+        return mDisplayContent.supportsSystemDecorations();
     }
 
     @VisibleForTesting
@@ -1135,7 +1145,30 @@
     }
 
     void setFocusedApp(ActivityRecord r, boolean moveFocusNow) {
-        mWindowContainerController.setFocusedApp(r.appToken, moveFocusNow);
+        if (mDisplayContent == null) {
+            return;
+        }
+        final AppWindowToken newFocus;
+        final IBinder token = r.appToken;
+        if (token == null) {
+            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Clearing focused app, displayId="
+                    + mDisplayId);
+            newFocus = null;
+        } else {
+            newFocus = mService.mWindowManager.mRoot.getAppWindowToken(token);
+            if (newFocus == null) {
+                Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token
+                        + ", displayId=" + mDisplayId);
+            }
+            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Set focused app to: " + newFocus
+                    + " moveFocusNow=" + moveFocusNow + " displayId=" + mDisplayId);
+        }
+
+        final boolean changed = mDisplayContent.setFocusedApp(newFocus);
+        if (moveFocusNow && changed) {
+            mService.mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
+                    true /*updateInputWindows*/);
+        }
     }
 
     /**
@@ -1283,17 +1316,21 @@
     }
 
     /**
-     * See {@link DisplayWindowController#deferUpdateImeTarget()}
+     * See {@link DisplayContent#deferUpdateImeTarget()}
      */
     public void deferUpdateImeTarget() {
-        mWindowContainerController.deferUpdateImeTarget();
+        if (mDisplayContent != null) {
+            mDisplayContent.deferUpdateImeTarget();
+        }
     }
 
     /**
-     * See {@link DisplayWindowController#deferUpdateImeTarget()}
+     * See {@link DisplayContent#deferUpdateImeTarget()}
      */
     public void continueUpdateImeTarget() {
-        mWindowContainerController.continueUpdateImeTarget();
+        if (mDisplayContent != null) {
+            mDisplayContent.continueUpdateImeTarget();
+        }
     }
 
     public void dump(PrintWriter pw, String prefix) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index daf4b8b..4e9c5ab 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -441,8 +441,13 @@
         mLastReportedConfiguration.dump(pw, prefix + " ");
 
         pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration());
-        if (!getOverrideConfiguration().equals(EMPTY)) {
-            pw.println(prefix + "OverrideConfiguration=" + getOverrideConfiguration());
+        if (!getRequestedOverrideConfiguration().equals(EMPTY)) {
+            pw.println(prefix + "RequestedOverrideConfiguration="
+                    + getRequestedOverrideConfiguration());
+        }
+        if (!getResolvedOverrideConfiguration().equals(getRequestedOverrideConfiguration())) {
+            pw.println(prefix + "ResolvedOverrideConfiguration="
+                    + getResolvedOverrideConfiguration());
         }
         if (!matchParentBounds()) {
             pw.println(prefix + "bounds=" + getBounds());
@@ -2531,13 +2536,13 @@
         mTmpConfig.unset();
         computeBounds(mTmpBounds);
 
-        if (mTmpBounds.equals(getOverrideBounds())) {
+        if (mTmpBounds.equals(getRequestedOverrideBounds())) {
             return;
         }
 
         setBounds(mTmpBounds);
 
-        final Rect updatedBounds = getOverrideBounds();
+        final Rect updatedBounds = getRequestedOverrideBounds();
 
         // Bounds changed...update configuration to match.
         if (!matchParentBounds()) {
@@ -2545,7 +2550,7 @@
                     false /* overrideWidth */, false /* overrideHeight */);
         }
 
-        onOverrideConfigurationChanged(mTmpConfig);
+        onRequestedOverrideConfigurationChanged(mTmpConfig);
     }
 
     /** Returns true if the configuration is compatible with this activity. */
@@ -2602,11 +2607,11 @@
         if (containingAppWidth <= maxActivityWidth && containingAppHeight <= maxActivityHeight) {
             // The display matches or is less than the activity aspect ratio, so nothing else to do.
             // Return the existing bounds. If this method is running for the first time,
-            // {@link #getOverrideBounds()} will be empty (representing no override). If the method has run
-            // before, then effect of {@link #getOverrideBounds()} will already have been applied to the
-            // value returned from {@link getConfiguration}. Refer to
-            // {@link TaskRecord#computeOverrideConfiguration}.
-            outBounds.set(getOverrideBounds());
+            // {@link #getRequestedOverrideBounds()} will be empty (representing no override). If
+            // the method has run before, then effect of {@link #getRequestedOverrideBounds()} will
+            // already have been applied to the value returned from {@link getConfiguration}. Refer
+            // to {@link TaskRecord#computeOverrideConfiguration}.
+            outBounds.set(getRequestedOverrideBounds());
             return;
         }
 
@@ -2937,7 +2942,7 @@
             final ActivityLifecycleItem lifecycleItem;
             if (andResume) {
                 lifecycleItem = ResumeActivityItem.obtain(
-                        getDisplay().getWindowContainerController().isNextTransitionForward());
+                        getDisplay().mDisplayContent.isNextTransitionForward());
             } else {
                 lifecycleItem = PauseActivityItem.obtain();
             }
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 3ccede0..7683172 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -264,8 +264,8 @@
             // If we created a docked stack we want to resize it so it resizes all other stacks
             // in the system.
             getStackDockedModeBounds(null, null, mTmpRect2, mTmpRect3);
-            mStackSupervisor.resizeDockedStackLocked(
-                    getOverrideBounds(), mTmpRect2, mTmpRect2, null, null, PRESERVE_WINDOWS);
+            mStackSupervisor.resizeDockedStackLocked(getRequestedOverrideBounds(), mTmpRect2,
+                    mTmpRect2, null, null, PRESERVE_WINDOWS);
         }
         mRootActivityContainer.updateUIDsPresentOnDisplay();
     }
@@ -562,7 +562,7 @@
         // Update bounds if applicable
         boolean hasNewOverrideBounds = false;
         // Use override windowing mode to prevent extra bounds changes if inheriting the mode.
-        if (getOverrideWindowingMode() == WINDOWING_MODE_PINNED) {
+        if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_PINNED) {
             // Pinned calculation already includes rotation
             mTmpRect2.set(mTmpRect);
             hasNewOverrideBounds = getWindowContainerController().mContainer
@@ -574,7 +574,7 @@
                 // bounds were on the pre-rotated display.
                 if (prevRotation != newRotation) {
                     mTmpRect2.set(mTmpRect);
-                    getDisplay().getWindowContainerController().mContainer
+                    getDisplay().mDisplayContent
                             .rotateBounds(newParentConfig.windowConfiguration.getBounds(),
                                     prevRotation, newRotation, mTmpRect2);
                     hasNewOverrideBounds = true;
@@ -589,8 +589,8 @@
                         || prevScreenH != getConfiguration().screenHeightDp) {
                     // Use override windowing mode to prevent extra bounds changes if inheriting
                     // the mode.
-                    if (getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
-                            || getOverrideWindowingMode()
+                    if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+                            || getRequestedOverrideWindowingMode()
                             == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
                         mTmpRect2.set(mTmpRect);
                         getWindowContainerController().mContainer
@@ -602,14 +602,15 @@
         }
         if (getWindowingMode() != prevWindowingMode) {
             // Use override windowing mode to prevent extra bounds changes if inheriting the mode.
-            if (getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+            if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
                 getStackDockedModeBounds(null, null, mTmpRect2, mTmpRect3);
                 // immediately resize so docked bounds are available in onSplitScreenModeActivated
                 resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */);
-            } else if (getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
+            } else if (
+                    getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
                 Rect dockedBounds = display.getSplitScreenPrimaryStack().getBounds();
-                final boolean isMinimizedDock = getDisplay().getWindowContainerController()
-                        .mContainer.getDockedDividerController().isMinimizedDock();
+                final boolean isMinimizedDock =
+                        getDisplay().mDisplayContent.getDockedDividerController().isMinimizedDock();
                 if (isMinimizedDock) {
                     TaskRecord topTask = display.getSplitScreenPrimaryStack().topTask();
                     if (topTask != null) {
@@ -672,7 +673,7 @@
     void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents,
             boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, boolean creating) {
         final int currentMode = getWindowingMode();
-        final int currentOverrideMode = getOverrideWindowingMode();
+        final int currentOverrideMode = getRequestedOverrideWindowingMode();
         final ActivityDisplay display = getDisplay();
         final TaskRecord topTask = topTask();
         final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack();
@@ -725,7 +726,7 @@
             // You are already in the window mode, so we can skip most of the work below. However,
             // it's possible that we have inherited the current windowing mode from a parent. So,
             // fulfill this method's contract by setting the override mode directly.
-            getOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
+            getRequestedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
             return;
         }
 
@@ -791,7 +792,7 @@
                 mWindowContainerController.getRawBounds(mTmpRect2);
             }
 
-            if (!Objects.equals(getOverrideBounds(), mTmpRect2)) {
+            if (!Objects.equals(getRequestedOverrideBounds(), mTmpRect2)) {
                 resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */);
             }
         } finally {
@@ -2713,16 +2714,16 @@
         // that the previous one will be hidden soon.  This way it can know
         // to ignore it when computing the desired screen orientation.
         boolean anim = true;
-        final DisplayWindowController dwc = getDisplay().getWindowContainerController();
+        final DisplayContent dc = getDisplay().mDisplayContent;
         if (prev != null) {
             if (prev.finishing) {
                 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                         "Prepare close transition: prev=" + prev);
                 if (mStackSupervisor.mNoAnimActivities.contains(prev)) {
                     anim = false;
-                    dwc.prepareAppTransition(TRANSIT_NONE, false);
+                    dc.prepareAppTransition(TRANSIT_NONE, false);
                 } else {
-                    dwc.prepareAppTransition(
+                    dc.prepareAppTransition(
                             prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_CLOSE
                                     : TRANSIT_TASK_CLOSE, false);
                 }
@@ -2732,9 +2733,9 @@
                         "Prepare open transition: prev=" + prev);
                 if (mStackSupervisor.mNoAnimActivities.contains(next)) {
                     anim = false;
-                    dwc.prepareAppTransition(TRANSIT_NONE, false);
+                    dc.prepareAppTransition(TRANSIT_NONE, false);
                 } else {
-                    dwc.prepareAppTransition(
+                    dc.prepareAppTransition(
                             prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_OPEN
                                     : next.mLaunchTaskBehind ? TRANSIT_TASK_OPEN_BEHIND
                                             : TRANSIT_TASK_OPEN, false);
@@ -2744,9 +2745,9 @@
             if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
             if (mStackSupervisor.mNoAnimActivities.contains(next)) {
                 anim = false;
-                dwc.prepareAppTransition(TRANSIT_NONE, false);
+                dc.prepareAppTransition(TRANSIT_NONE, false);
             } else {
-                dwc.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
+                dc.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
             }
         }
 
@@ -2868,8 +2869,7 @@
                 next.clearOptionsLocked();
                 transaction.setLifecycleStateRequest(
                         ResumeActivityItem.obtain(next.app.getReportedProcState(),
-                                getDisplay().getWindowContainerController()
-                                        .isNextTransitionForward()));
+                                getDisplay().mDisplayContent.isNextTransitionForward()));
                 mService.getLifecycleManager().scheduleTransaction(transaction);
 
                 if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
@@ -3071,11 +3071,11 @@
         task.setFrontOfTask();
 
         if (!isHomeOrRecentsStack() || numActivities() > 0) {
-            final DisplayWindowController dwc = getDisplay().getWindowContainerController();
+            final DisplayContent dc = getDisplay().mDisplayContent;
             if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                     "Prepare open transition: starting " + r);
             if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
-                dwc.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
+                dc.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
                 mStackSupervisor.mNoAnimActivities.add(r);
             } else {
                 int transit = TRANSIT_ACTIVITY_OPEN;
@@ -3094,7 +3094,7 @@
                         transit = TRANSIT_TASK_OPEN;
                     }
                 }
-                dwc.prepareAppTransition(transit, keepCurTransition);
+                dc.prepareAppTransition(transit, keepCurTransition);
                 mStackSupervisor.mNoAnimActivities.remove(r);
             }
             boolean doShow = true;
@@ -3723,7 +3723,7 @@
         int taskNdx = mTaskHistory.indexOf(finishedTask);
         final TaskRecord task = finishedTask;
         int activityNdx = task.mActivities.indexOf(r);
-        getDisplay().getWindowContainerController().prepareAppTransition(
+        getDisplay().mDisplayContent.prepareAppTransition(
                 TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
         finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false);
         finishedTask = task;
@@ -3889,7 +3889,7 @@
                     mService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
                             task.taskId);
                 }
-                getDisplay().getWindowContainerController().prepareAppTransition(transit, false);
+                getDisplay().mDisplayContent.prepareAppTransition(transit, false);
 
                 // Tell window manager to prepare for this one to be removed.
                 r.setVisibility(false);
@@ -3944,10 +3944,10 @@
     }
 
     private void prepareActivityHideTransitionAnimation(ActivityRecord r, int transit) {
-        final DisplayWindowController dwc = getDisplay().getWindowContainerController();
-        dwc.prepareAppTransition(transit, false);
+        final DisplayContent dc = getDisplay().mDisplayContent;
+        dc.prepareAppTransition(transit, false);
         r.setVisibility(false);
-        dwc.executeAppTransition();
+        dc.executeAppTransition();
         if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(r)) {
             mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(r);
         }
@@ -4691,7 +4691,7 @@
                 ActivityOptions.abort(options);
             }
         }
-        getDisplay().getWindowContainerController().prepareAppTransition(transit, false);
+        getDisplay().mDisplayContent.prepareAppTransition(transit, false);
     }
 
     private void updateTaskMovement(TaskRecord task, boolean toFront) {
@@ -4760,8 +4760,7 @@
 
             if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
             if (noAnimation) {
-                getDisplay().getWindowContainerController().prepareAppTransition(
-                        TRANSIT_NONE, false);
+                getDisplay().mDisplayContent.prepareAppTransition(TRANSIT_NONE, false);
                 if (r != null) {
                     mStackSupervisor.mNoAnimActivities.add(r);
                 }
@@ -4843,8 +4842,7 @@
         mTaskHistory.add(0, tr);
         updateTaskMovement(tr, false);
 
-        getDisplay().getWindowContainerController().prepareAppTransition(
-                TRANSIT_TASK_TO_BACK, false);
+        getDisplay().mDisplayContent.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
         moveToBack("moveTaskToBackLocked", tr);
 
         if (inPinnedWindowingMode()) {
@@ -4934,8 +4932,8 @@
                     // For freeform stack we don't adjust the size of the tasks to match that
                     // of the stack, but we do try to make sure the tasks are still contained
                     // with the bounds of the stack.
-                    if (task.getOverrideBounds() != null) {
-                        mTmpRect2.set(task.getOverrideBounds());
+                    if (task.getRequestedOverrideBounds() != null) {
+                        mTmpRect2.set(task.getRequestedOverrideBounds());
                         fitWithinBounds(mTmpRect2, bounds);
                         task.updateOverrideConfiguration(mTmpRect2);
                     }
@@ -4946,9 +4944,9 @@
 
             if (task.hasDisplayedBounds()) {
                 mTmpBounds.put(task.taskId, task.getDisplayedBounds());
-                mTmpInsetBounds.put(task.taskId, task.getOverrideBounds());
+                mTmpInsetBounds.put(task.taskId, task.getRequestedOverrideBounds());
             } else {
-                mTmpBounds.put(task.taskId, task.getOverrideBounds());
+                mTmpBounds.put(task.taskId, task.getRequestedOverrideBounds());
                 mTmpInsetBounds.put(task.taskId, null);
             }
         }
@@ -5169,7 +5167,7 @@
                             + r.intent.getComponent().flattenToShortString());
                     // Force the destroy to skip right to removal.
                     r.app = null;
-                    getDisplay().getWindowContainerController().prepareAppTransition(
+                    getDisplay().mDisplayContent.prepareAppTransition(
                             TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
                     finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false,
                             "handleAppCrashedLocked");
@@ -5191,7 +5189,7 @@
                 pw.println("");
             }
             pw.println(prefix + "Task id #" + task.taskId);
-            pw.println(prefix + "mBounds=" + task.getOverrideBounds());
+            pw.println(prefix + "mBounds=" + task.getRequestedOverrideBounds());
             pw.println(prefix + "mMinWidth=" + task.mMinWidth);
             pw.println(prefix + "mMinHeight=" + task.mMinHeight);
             pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds);
@@ -5349,7 +5347,7 @@
         if (!mStackSupervisor.getLaunchParamsController()
                 .layoutTask(task, info.windowLayout, activity, source, options)
                 && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
-            task.updateOverrideConfiguration(getOverrideBounds());
+            task.updateOverrideConfiguration(getRequestedOverrideBounds());
         }
         task.createWindowContainer(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
         return task;
@@ -5507,7 +5505,7 @@
     }
 
     void executeAppTransition(ActivityOptions options) {
-        getDisplay().getWindowContainerController().executeAppTransition();
+        getDisplay().mDisplayContent.executeAppTransition();
         ActivityOptions.abort(options);
     }
 
@@ -5541,7 +5539,7 @@
         }
         proto.write(DISPLAY_ID, mDisplayId);
         if (!matchParentBounds()) {
-            final Rect bounds = getOverrideBounds();
+            final Rect bounds = getRequestedOverrideBounds();
             bounds.writeToProto(proto, BOUNDS);
         }
 
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index f3c5630..e761ad8 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -818,7 +818,7 @@
                 final ClientTransaction clientTransaction = ClientTransaction.obtain(
                         proc.getThread(), r.appToken);
 
-                final DisplayWindowController dwc = r.getDisplay().getWindowContainerController();
+                final DisplayContent dc = r.getDisplay().mDisplayContent;
                 clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                         System.identityHashCode(r), r.info,
                         // TODO: Have this take the merged configuration instead of separate global
@@ -827,12 +827,12 @@
                         mergedConfiguration.getOverrideConfiguration(), r.compat,
                         r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
                         r.icicle, r.persistentState, results, newIntents,
-                        dwc.isNextTransitionForward(), profilerInfo));
+                        dc.isNextTransitionForward(), profilerInfo));
 
                 // Set desired final state.
                 final ActivityLifecycleItem lifecycleItem;
                 if (andResume) {
-                    lifecycleItem = ResumeActivityItem.obtain(dwc.isNextTransitionForward());
+                    lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
                 } else {
                     lifecycleItem = PauseActivityItem.obtain();
                 }
@@ -2410,7 +2410,7 @@
             return;
         }
 
-        scheduleUpdatePictureInPictureModeIfNeeded(task, stack.getOverrideBounds());
+        scheduleUpdatePictureInPictureModeIfNeeded(task, stack.getRequestedOverrideBounds());
     }
 
     void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, Rect targetStackBounds) {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index bc2136e..4538d36 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1565,7 +1565,7 @@
                 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                 // Go ahead and tell window manager to execute app transition for this activity
                 // since the app transition will not be triggered through the resume channel.
-                mTargetStack.getDisplay().getWindowContainerController().executeAppTransition();
+                mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
             } else {
                 // If the target stack was not previously focusable (previous top running activity
                 // on that stack was not visible) then any prior calls to move the stack to the
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 61eb9d4..182d1a0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1738,7 +1738,7 @@
 
             if (self.isState(
                     ActivityStack.ActivityState.RESUMED, ActivityStack.ActivityState.PAUSING)) {
-                self.getDisplay().getWindowContainerController().overridePendingAppTransition(
+                self.getDisplay().mDisplayContent.mAppTransition.overridePendingAppTransition(
                         packageName, enterAnim, exitAnim, null);
             }
 
@@ -3073,12 +3073,11 @@
         // Get top display of front most application.
         final ActivityStack focusedStack = getTopDisplayFocusedStack();
         if (focusedStack != null) {
-            final DisplayWindowController dwc =
-                    focusedStack.getDisplay().getWindowContainerController();
-            dwc.prepareAppTransition(TRANSIT_TASK_IN_PLACE, false);
-            dwc.overridePendingAppTransitionInPlace(activityOptions.getPackageName(),
+            final DisplayContent dc = focusedStack.getDisplay().mDisplayContent;
+            dc.prepareAppTransition(TRANSIT_TASK_IN_PLACE, false);
+            dc.mAppTransition.overrideInPlaceAppTransition(activityOptions.getPackageName(),
                     activityOptions.getCustomInPlaceResId());
-            dwc.executeAppTransition();
+            dc.executeAppTransition();
         }
     }
 
@@ -5770,17 +5769,18 @@
                 if (activityDisplay == null) {
                     return;
                 }
-                final DisplayWindowController dwc = activityDisplay.getWindowContainerController();
-                final boolean wasTransitionSet = dwc.getPendingAppTransition() != TRANSIT_NONE;
+                final DisplayContent dc = activityDisplay.mDisplayContent;
+                final boolean wasTransitionSet =
+                        dc.mAppTransition.getAppTransition() != TRANSIT_NONE;
                 if (!wasTransitionSet) {
-                    dwc.prepareAppTransition(TRANSIT_NONE, false /* alwaysKeepCurrent */);
+                    dc.prepareAppTransition(TRANSIT_NONE, false /* alwaysKeepCurrent */);
                 }
                 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
 
                 // If there was a transition set already we don't want to interfere with it as we
                 // might be starting it too early.
                 if (!wasTransitionSet) {
-                    dwc.executeAppTransition();
+                    dc.executeAppTransition();
                 }
             }
             if (callback != null) {
@@ -6270,18 +6270,20 @@
                     finishInstrumentationCallback.run();
                 }
 
-                mWindowManager.deferSurfaceLayout();
-                try {
-                    if (!restarting && hasVisibleActivities
-                            && !mRootActivityContainer.resumeFocusedStacksTopActivities()) {
-                        // If there was nothing to resume, and we are not already restarting this
-                        // process, but there is a visible activity that is hosted by the process...
-                        // then make sure all visible activities are running, taking care of
-                        // restarting this process.
-                        mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+                if (!restarting && hasVisibleActivities) {
+                    mWindowManager.deferSurfaceLayout();
+                    try {
+                        if (!mRootActivityContainer.resumeFocusedStacksTopActivities()) {
+                            // If there was nothing to resume, and we are not already restarting
+                            // this process, but there is a visible activity that is hosted by the
+                            // process...then make sure all visible activities are running, taking
+                            // care of restarting this process.
+                            mRootActivityContainer.ensureActivitiesVisible(null, 0,
+                                    !PRESERVE_WINDOWS);
+                        }
+                    } finally {
+                        mWindowManager.continueSurfaceLayout();
                     }
-                } finally {
-                    mWindowManager.continueSurfaceLayout();
                 }
             }
         }
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index e779d1b..ded45c9 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -49,20 +49,28 @@
  */
 public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
     /**
-     * {@link #Rect} returned from {@link #getOverrideBounds()} to prevent original value from being
-     * set directly.
+     * {@link #Rect} returned from {@link #getRequestedOverrideBounds()} to prevent original value
+     * from being set directly.
      */
     private Rect mReturnBounds = new Rect();
 
-    /** Contains override configuration settings applied to this configuration container. */
-    private Configuration mOverrideConfiguration = new Configuration();
+    /**
+     * Contains requested override configuration settings applied to this configuration container.
+     */
+    private Configuration mRequestedOverrideConfiguration = new Configuration();
 
-    /** True if mOverrideConfiguration is not empty */
+    /**
+     * Contains the requested override configuration with parent and policy constraints applied.
+     * This is the set of overrides that gets applied to the full and merged configurations.
+     */
+    private Configuration mResolvedOverrideConfiguration = new Configuration();
+
+    /** True if mRequestedOverrideConfiguration is not empty */
     private boolean mHasOverrideConfiguration;
 
     /**
      * Contains full configuration applied to this configuration container. Corresponds to full
-     * parent's config with applied {@link #mOverrideConfiguration}.
+     * parent's config with applied {@link #mResolvedOverrideConfiguration}.
      */
     private Configuration mFullConfiguration = new Configuration();
 
@@ -102,41 +110,62 @@
      * @see #mFullConfiguration
      */
     public void onConfigurationChanged(Configuration newParentConfig) {
+        mTmpConfig.setTo(mResolvedOverrideConfiguration);
+        resolveOverrideConfiguration(newParentConfig);
         mFullConfiguration.setTo(newParentConfig);
-        mFullConfiguration.updateFrom(mOverrideConfiguration);
+        mFullConfiguration.updateFrom(mResolvedOverrideConfiguration);
+        if (!mTmpConfig.equals(mResolvedOverrideConfiguration)) {
+            onMergedOverrideConfigurationChanged();
+            // This depends on the assumption that change-listeners don't do
+            // their own override resolution. This way, dependent hierarchies
+            // can stay properly synced-up with a primary hierarchy's constraints.
+            // Since the hierarchies will be merged, this whole thing will go away
+            // before the assumption will be broken.
+            // Inform listeners of the change.
+            for (int i = mChangeListeners.size() - 1; i >= 0; --i) {
+                mChangeListeners.get(i).onRequestedOverrideConfigurationChanged(
+                        mResolvedOverrideConfiguration);
+            }
+        }
         for (int i = getChildCount() - 1; i >= 0; --i) {
             final ConfigurationContainer child = getChildAt(i);
             child.onConfigurationChanged(mFullConfiguration);
         }
     }
 
-    /** Returns override configuration applied to this configuration container. */
-    public Configuration getOverrideConfiguration() {
-        return mOverrideConfiguration;
+    /**
+     * Resolves the current requested override configuration into
+     * {@link #mResolvedOverrideConfiguration}
+     *
+     * @param newParentConfig The new parent configuration to resolve overrides against.
+     */
+    void resolveOverrideConfiguration(Configuration newParentConfig) {
+        mResolvedOverrideConfiguration.setTo(mRequestedOverrideConfiguration);
+    }
+
+    /** Returns requested override configuration applied to this configuration container. */
+    public Configuration getRequestedOverrideConfiguration() {
+        return mRequestedOverrideConfiguration;
+    }
+
+    /** Returns the resolved override configuration. */
+    Configuration getResolvedOverrideConfiguration() {
+        return mResolvedOverrideConfiguration;
     }
 
     /**
      * Update override configuration and recalculate full config.
-     * @see #mOverrideConfiguration
+     * @see #mRequestedOverrideConfiguration
      * @see #mFullConfiguration
      */
-    public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+    public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
         // Pre-compute this here, so we don't need to go through the entire Configuration when
         // writing to proto (which has significant cost if we write a lot of empty configurations).
         mHasOverrideConfiguration = !Configuration.EMPTY.equals(overrideConfiguration);
-        mOverrideConfiguration.setTo(overrideConfiguration);
+        mRequestedOverrideConfiguration.setTo(overrideConfiguration);
         // Update full configuration of this container and all its children.
         final ConfigurationContainer parent = getParent();
         onConfigurationChanged(parent != null ? parent.getConfiguration() : Configuration.EMPTY);
-        // Update merged override config of this container and all its children.
-        onMergedOverrideConfigurationChanged();
-
-        // Use the updated override configuration to notify listeners.
-        mTmpConfig.setTo(mOverrideConfiguration);
-        // Inform listeners of the change.
-        for (int i = mChangeListeners.size() - 1; i >=0; --i) {
-            mChangeListeners.get(i).onOverrideConfigurationChanged(mTmpConfig);
-        }
     }
 
     /**
@@ -157,9 +186,9 @@
         final ConfigurationContainer parent = getParent();
         if (parent != null) {
             mMergedOverrideConfiguration.setTo(parent.getMergedOverrideConfiguration());
-            mMergedOverrideConfiguration.updateFrom(mOverrideConfiguration);
+            mMergedOverrideConfiguration.updateFrom(mResolvedOverrideConfiguration);
         } else {
-            mMergedOverrideConfiguration.setTo(mOverrideConfiguration);
+            mMergedOverrideConfiguration.setTo(mResolvedOverrideConfiguration);
         }
         for (int i = getChildCount() - 1; i >= 0; --i) {
             final ConfigurationContainer child = getChildAt(i);
@@ -168,24 +197,26 @@
     }
 
     /**
-     * Indicates whether this container has not specified any bounds different from its parent. In
-     * this case, it will inherit the bounds of the first ancestor which specifies a bounds.
-     * @return {@code true} if no explicit bounds have been set at this container level.
+     * Indicates whether this container has not requested any bounds different from its parent. In
+     * this case, it will inherit the bounds of the first ancestor which specifies a bounds subject
+     * to policy constraints.
+     *
+     * @return {@code true} if no explicit bounds have been requested at this container level.
      *         {@code false} otherwise.
      */
     public boolean matchParentBounds() {
-        return getOverrideBounds().isEmpty();
+        return getRequestedOverrideBounds().isEmpty();
     }
 
     /**
-     * Returns whether the bounds specified is considered the same as the existing override bounds.
-     * This is either when the two bounds are equal or the override bounds is empty and the
-     * specified bounds is null.
+     * Returns whether the bounds specified are considered the same as the existing requested
+     * override bounds. This is either when the two bounds are equal or the requested override
+     * bounds are empty and the specified bounds is null.
      *
      * @return {@code true} if the bounds are equivalent, {@code false} otherwise
      */
-    public boolean equivalentOverrideBounds(Rect bounds) {
-        return equivalentBounds(getOverrideBounds(),  bounds);
+    public boolean equivalentRequestedOverrideBounds(Rect bounds) {
+        return equivalentBounds(getRequestedOverrideBounds(),  bounds);
     }
 
     /**
@@ -212,50 +243,52 @@
     }
 
     /**
-     * Returns the current bounds explicitly set on this container. The {@link Rect} handed back is
+     * Returns the bounds requested on this container. These may not be the actual bounds the
+     * container ends up with due to policy constraints. The {@link Rect} handed back is
      * shared for all calls to this method and should not be modified.
      */
-    public Rect getOverrideBounds() {
-        mReturnBounds.set(getOverrideConfiguration().windowConfiguration.getBounds());
+    public Rect getRequestedOverrideBounds() {
+        mReturnBounds.set(getRequestedOverrideConfiguration().windowConfiguration.getBounds());
 
         return mReturnBounds;
     }
 
     /**
-     * Returns {@code true} if the {@link WindowConfiguration} in the override
+     * Returns {@code true} if the {@link WindowConfiguration} in the requested override
      * {@link Configuration} specifies bounds.
      */
     public boolean hasOverrideBounds() {
-        return !getOverrideBounds().isEmpty();
+        return !getRequestedOverrideBounds().isEmpty();
     }
 
     /**
      * Sets the passed in {@link Rect} to the current bounds.
-     * @see {@link #getOverrideBounds()}.
+     * @see {@link #getRequestedOverrideBounds()}.
      */
-    public void getOverrideBounds(Rect outBounds) {
-        outBounds.set(getOverrideBounds());
+    public void getRequestedOverrideBounds(Rect outBounds) {
+        outBounds.set(getRequestedOverrideBounds());
     }
 
     /**
      * Sets the bounds at the current hierarchy level, overriding any bounds set on an ancestor.
-     * This value will be reported when {@link #getBounds()} and {@link #getOverrideBounds()}. If
+     * This value will be reported when {@link #getBounds()} and
+     * {@link #getRequestedOverrideBounds()}. If
      * an empty {@link Rect} or null is specified, this container will be considered to match its
      * parent bounds {@see #matchParentBounds} and will inherit bounds from its parent.
      * @param bounds The bounds defining the container size.
      * @return a bitmask representing the types of changes made to the bounds.
      */
     public int setBounds(Rect bounds) {
-        int boundsChange = diffOverrideBounds(bounds);
+        int boundsChange = diffRequestedOverrideBounds(bounds);
 
         if (boundsChange == BOUNDS_CHANGE_NONE) {
             return boundsChange;
         }
 
 
-        mTmpConfig.setTo(getOverrideConfiguration());
+        mTmpConfig.setTo(getRequestedOverrideConfiguration());
         mTmpConfig.windowConfiguration.setBounds(bounds);
-        onOverrideConfigurationChanged(mTmpConfig);
+        onRequestedOverrideConfigurationChanged(mTmpConfig);
 
         return boundsChange;
     }
@@ -265,14 +298,14 @@
         return setBounds(mTmpRect);
     }
 
-    int diffOverrideBounds(Rect bounds) {
-        if (equivalentOverrideBounds(bounds)) {
+    int diffRequestedOverrideBounds(Rect bounds) {
+        if (equivalentRequestedOverrideBounds(bounds)) {
             return BOUNDS_CHANGE_NONE;
         }
 
         int boundsChange = BOUNDS_CHANGE_NONE;
 
-        final Rect existingBounds = getOverrideBounds();
+        final Rect existingBounds = getRequestedOverrideBounds();
 
         if (bounds == null || existingBounds.left != bounds.left
                 || existingBounds.top != bounds.top) {
@@ -296,15 +329,16 @@
         return mFullConfiguration.windowConfiguration.getWindowingMode();
     }
 
-    public int getOverrideWindowingMode() {
-        return mOverrideConfiguration.windowConfiguration.getWindowingMode();
+    /** Returns the windowing mode override that is requested by this container. */
+    public int getRequestedOverrideWindowingMode() {
+        return mRequestedOverrideConfiguration.windowConfiguration.getWindowingMode();
     }
 
-    /** Sets the windowing mode for the configuration container. */
+    /** Sets the requested windowing mode override for the configuration container. */
     public void setWindowingMode(/*@WindowConfiguration.WindowingMode*/ int windowingMode) {
-        mTmpConfig.setTo(getOverrideConfiguration());
+        mTmpConfig.setTo(getRequestedOverrideConfiguration());
         mTmpConfig.windowConfiguration.setWindowingMode(windowingMode);
-        onOverrideConfigurationChanged(mTmpConfig);
+        onRequestedOverrideConfigurationChanged(mTmpConfig);
     }
 
     /** Sets the always on top flag for this configuration container.
@@ -314,16 +348,16 @@
      *  - {@Link ActivityDisplay#positionChildAtTop(ActivityStack)};
      * */
     public void setAlwaysOnTop(boolean alwaysOnTop) {
-        mTmpConfig.setTo(getOverrideConfiguration());
+        mTmpConfig.setTo(getRequestedOverrideConfiguration());
         mTmpConfig.windowConfiguration.setAlwaysOnTop(alwaysOnTop);
-        onOverrideConfigurationChanged(mTmpConfig);
+        onRequestedOverrideConfigurationChanged(mTmpConfig);
     }
 
     /** Sets the windowing mode for the configuration container. */
     void setDisplayWindowingMode(int windowingMode) {
-        mTmpConfig.setTo(getOverrideConfiguration());
+        mTmpConfig.setTo(getRequestedOverrideConfiguration());
         mTmpConfig.windowConfiguration.setDisplayWindowingMode(windowingMode);
-        onOverrideConfigurationChanged(mTmpConfig);
+        onRequestedOverrideConfigurationChanged(mTmpConfig);
     }
 
     /**
@@ -393,9 +427,9 @@
             throw new IllegalStateException("Can't change activity type once set: " + this
                     + " activityType=" + activityTypeToString(activityType));
         }
-        mTmpConfig.setTo(getOverrideConfiguration());
+        mTmpConfig.setTo(getRequestedOverrideConfiguration());
         mTmpConfig.windowConfiguration.setActivityType(activityType);
-        onOverrideConfigurationChanged(mTmpConfig);
+        onRequestedOverrideConfigurationChanged(mTmpConfig);
     }
 
     public boolean isActivityTypeHome() {
@@ -472,7 +506,7 @@
             return;
         }
         mChangeListeners.add(listener);
-        listener.onOverrideConfigurationChanged(mOverrideConfiguration);
+        listener.onRequestedOverrideConfigurationChanged(mResolvedOverrideConfiguration);
     }
 
     public void unregisterConfigurationChangeListener(ConfigurationContainerListener listener) {
@@ -508,7 +542,7 @@
     public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
         final long token = proto.start(fieldId);
         if (!trim || mHasOverrideConfiguration) {
-            mOverrideConfiguration.writeToProto(proto, OVERRIDE_CONFIGURATION);
+            mRequestedOverrideConfiguration.writeToProto(proto, OVERRIDE_CONFIGURATION);
         }
         if (!trim) {
             mFullConfiguration.writeToProto(proto, FULL_CONFIGURATION);
@@ -526,7 +560,7 @@
         pw.println(getName()
                 + " type=" + activityTypeToString(getActivityType())
                 + " mode=" + windowingModeToString(getWindowingMode())
-                + " override-mode=" + windowingModeToString(getOverrideWindowingMode()));
+                + " override-mode=" + windowingModeToString(getRequestedOverrideWindowingMode()));
         for (int i = getChildCount() - 1; i >= 0; --i) {
             final E cc = getChildAt(i);
             pw.print(childPrefix + "#" + i + " ");
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainerListener.java b/services/core/java/com/android/server/wm/ConfigurationContainerListener.java
index ff14d97..dc4939d 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainerListener.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainerListener.java
@@ -23,5 +23,6 @@
  */
 public interface ConfigurationContainerListener {
 
-    void onOverrideConfigurationChanged(Configuration overrideConfiguration);
+    /** {@see ConfigurationContainer#onRequestedOverrideConfigurationChanged} */
+    void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration);
 }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index aba2eb3..2f4c5ca 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -59,8 +59,11 @@
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
 
+import static android.view.WindowManager.TRANSIT_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
@@ -207,6 +210,9 @@
     /** Unique identifier of this stack. */
     private final int mDisplayId;
 
+    // TODO: Remove once unification is complete.
+    ActivityDisplay mAcitvityDisplay;
+
     /** The containers below are the only child containers the display can have. */
     // Contains all window containers that are related to apps (Activities)
     private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(mWmService);
@@ -227,7 +233,6 @@
 
     private WindowState mTmpWindow;
     private WindowState mTmpWindow2;
-    private WindowAnimator mTmpWindowAnimator;
     private boolean mTmpRecoveringMemory;
     private boolean mUpdateImeTarget;
     private boolean mTmpInitial;
@@ -827,12 +832,12 @@
      * initialize direct children.
      * @param display May not be null.
      * @param service You know.
-     * @param controller The controller for the display container.
+     * @param activityDisplay The ActivityDisplay for the display container.
      */
     DisplayContent(Display display, WindowManagerService service,
-            DisplayWindowController controller) {
+            ActivityDisplay activityDisplay) {
         super(service);
-        setController(controller);
+        mAcitvityDisplay = activityDisplay;
         if (service.mRoot.getDisplayContent(display.getDisplayId()) != null) {
             throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
                     + " already exists=" + service.mRoot.getDisplayContent(display.getDisplayId())
@@ -1020,11 +1025,6 @@
     }
 
     @Override
-    DisplayWindowController getController() {
-        return (DisplayWindowController) super.getController();
-    }
-
-    @Override
     public Display getDisplay() {
         return mDisplay;
     }
@@ -1138,6 +1138,17 @@
         return true;
     }
 
+    /**
+     * The display content may have configuration set from {@link #DisplayWindowSettings}. This
+     * callback let the owner of container know there is existing configuration to prevent the
+     * values from being replaced by the initializing {@link #ActivityDisplay}.
+     */
+    void initializeDisplayOverrideConfiguration() {
+        if (mAcitvityDisplay != null) {
+            mAcitvityDisplay.onInitializeOverrideConfiguration(getRequestedOverrideConfiguration());
+        }
+    }
+
     /** Notify the configuration change of this display. */
     void sendNewConfiguration() {
         mWmService.mH.obtainMessage(SEND_NEW_CONFIGURATION, this).sendToTarget();
@@ -4686,6 +4697,11 @@
     }
 
     void prepareAppTransition(@WindowManager.TransitionType int transit,
+            boolean alwaysKeepCurrent) {
+        prepareAppTransition(transit, alwaysKeepCurrent, 0 /* flags */, false /* forceOverride */);
+    }
+
+    void prepareAppTransition(@WindowManager.TransitionType int transit,
             boolean alwaysKeepCurrent, @WindowManager.TransitionFlags int flags,
             boolean forceOverride) {
         final boolean prepared = mAppTransition.prepareAppTransitionLocked(
@@ -4737,6 +4753,14 @@
         pendingLayoutChanges |= changes;
     }
 
+    /** Check if pending app transition is for activity / task launch. */
+    boolean isNextTransitionForward() {
+        final int transit = mAppTransition.getAppTransition();
+        return transit == TRANSIT_ACTIVITY_OPEN
+                || transit == TRANSIT_TASK_OPEN
+                || transit == TRANSIT_TASK_TO_FRONT;
+    }
+
     /**
      * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
      */
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index d4bd91b..8b8cadc 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -763,6 +763,12 @@
                         || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
                     attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
                 }
+                // Accessibility users may need longer timeout duration. This api compares
+                // original timeout with user's preference and return longer one. It returns
+                // original timeout if there's no preference.
+                attrs.hideTimeoutMilliseconds = mAccessibilityManager.getRecommendedTimeoutMillis(
+                        (int) attrs.hideTimeoutMilliseconds,
+                        AccessibilityManager.FLAG_CONTENT_TEXT);
                 attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
                 break;
         }
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
deleted file mode 100644
index 55b3def..0000000
--- a/services/core/java/com/android/server/wm/DisplayWindowController.java
+++ /dev/null
@@ -1,357 +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.server.wm;
-
-import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN;
-import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
-
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
-
-import android.content.res.Configuration;
-import android.graphics.GraphicBuffer;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.IRemoteCallback;
-import android.util.Slog;
-import android.view.AppTransitionAnimationSpec;
-import android.view.Display;
-import android.view.WindowManager;
-import android.view.WindowManager.TransitionType;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Controller for the display container. This is created by activity manager to link activity
- * displays to the display content they use in window manager.
- */
-public class DisplayWindowController
-        extends WindowContainerController<DisplayContent, WindowContainerListener> {
-
-    private final int mDisplayId;
-
-    public DisplayWindowController(Display display, WindowContainerListener listener) {
-        super(listener, WindowManagerService.getInstance());
-        mDisplayId = display.getDisplayId();
-
-        synchronized (mGlobalLock) {
-            final long callingIdentity = Binder.clearCallingIdentity();
-            try {
-                mRoot.createDisplayContent(display, this /* controller */);
-            } finally {
-                Binder.restoreCallingIdentity(callingIdentity);
-            }
-
-            if (mContainer == null) {
-                throw new IllegalArgumentException("Trying to add display=" + display
-                        + " dc=" + mRoot.getDisplayContent(mDisplayId));
-            }
-        }
-    }
-
-    @VisibleForTesting
-    public DisplayWindowController(Display display, WindowManagerService service) {
-        super(null, service);
-        mDisplayId = display.getDisplayId();
-    }
-
-    @Override
-    public void removeContainer() {
-        synchronized (mGlobalLock) {
-            if(mContainer == null) {
-                if (DEBUG_DISPLAY) Slog.i(TAG_WM, "removeDisplay: could not find displayId="
-                        + mDisplayId);
-                return;
-            }
-            mContainer.removeIfPossible();
-            super.removeContainer();
-        }
-    }
-
-    @Override
-    public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
-        synchronized (mGlobalLock) {
-            if (mContainer != null) {
-                mContainer.mWmService.setNewDisplayOverrideConfiguration(overrideConfiguration,
-                        mContainer);
-            }
-        }
-    }
-
-    /**
-     * Updates the docked/pinned controller resources to the current system context.
-     */
-    public void preOnConfigurationChanged() {
-        synchronized (mGlobalLock) {
-            if (mContainer != null) {
-                mContainer.preOnConfigurationChanged();
-            }
-        }
-    }
-
-  /**
-   * @see DisplayContent#applyRotationLocked(int, int)
-   */
-    public void applyRotation(int oldRotation, int newRotation) {
-        synchronized (mGlobalLock) {
-            if (mContainer != null) {
-                mContainer.applyRotationLocked(oldRotation, newRotation);
-            }
-        }
-    }
-
-    public int getDisplayId() {
-        return mDisplayId;
-    }
-
-    /**
-     * Called when the corresponding display receives
-     * {@link android.hardware.display.DisplayManager.DisplayListener#onDisplayChanged(int)}.
-     */
-    public void onDisplayChanged() {
-        synchronized (mGlobalLock) {
-            if (mContainer == null) {
-                if (DEBUG_DISPLAY) Slog.i(TAG_WM, "onDisplayChanged: could not find display="
-                        + mDisplayId);
-                return;
-            }
-            mContainer.updateDisplayInfo();
-            mService.mWindowPlacerLocked.requestTraversal();
-        }
-    }
-
-    /**
-     * Positions the task stack at the given position in the task stack container.
-     */
-    public void positionChildAt(StackWindowController child, int position,
-            boolean includingParents) {
-        synchronized (mGlobalLock) {
-            if (DEBUG_STACK) Slog.i(TAG_WM, "positionTaskStackAt: positioning stack=" + child
-                    + " at " + position);
-            if (mContainer == null) {
-                if (DEBUG_STACK) Slog.i(TAG_WM,
-                        "positionTaskStackAt: could not find display=" + mContainer);
-                return;
-            }
-            if (child.mContainer == null) {
-                if (DEBUG_STACK) Slog.i(TAG_WM,
-                        "positionTaskStackAt: could not find stack=" + this);
-                return;
-            }
-            mContainer.positionStackAt(position, child.mContainer, includingParents);
-        }
-    }
-
-    /**
-     * Starts deferring the ability to update the IME target. This is needed when a call will
-     * attempt to update the IME target before all information about the Windows have been updated.
-     */
-    public void deferUpdateImeTarget() {
-        synchronized (mGlobalLock) {
-            final DisplayContent dc = mRoot.getDisplayContent(mDisplayId);
-            if (dc != null) {
-                dc.deferUpdateImeTarget();
-            }
-        }
-    }
-
-    /**
-     * Resumes updating the IME target after deferring. See {@link #deferUpdateImeTarget()}
-     */
-    public void continueUpdateImeTarget() {
-        synchronized (mGlobalLock) {
-            final DisplayContent dc = mRoot.getDisplayContent(mDisplayId);
-            if (dc != null) {
-                dc.continueUpdateImeTarget();
-            }
-        }
-    }
-
-    /**
-     * Sets a focused app on this display.
-     *
-     * @param token Specifies which app should be focused.
-     * @param moveFocusNow Specifies if we should update the focused window immediately.
-     */
-    public void setFocusedApp(IBinder token, boolean moveFocusNow) {
-        synchronized (mGlobalLock) {
-            if (mContainer == null) {
-                if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "setFocusedApp: could not find displayId="
-                        + mDisplayId);
-                return;
-            }
-            final AppWindowToken newFocus;
-            if (token == null) {
-                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Clearing focused app, displayId="
-                        + mDisplayId);
-                newFocus = null;
-            } else {
-                newFocus = mRoot.getAppWindowToken(token);
-                if (newFocus == null) {
-                    Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token
-                            + ", displayId=" + mDisplayId);
-                }
-                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Set focused app to: " + newFocus
-                        + " moveFocusNow=" + moveFocusNow + " displayId=" + mDisplayId);
-            }
-
-            final boolean changed = mContainer.setFocusedApp(newFocus);
-            if (moveFocusNow && changed) {
-                mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
-                        true /*updateInputWindows*/);
-            }
-        }
-    }
-
-    public void prepareAppTransition(@WindowManager.TransitionType int transit,
-            boolean alwaysKeepCurrent) {
-        prepareAppTransition(transit, alwaysKeepCurrent, 0 /* flags */, false /* forceOverride */);
-    }
-
-    /**
-     * @param transit What kind of transition is happening. Use one of the constants
-     *                AppTransition.TRANSIT_*.
-     * @param alwaysKeepCurrent If true and a transition is already set, new transition will NOT
-     *                          be set.
-     * @param flags Additional flags for the app transition, Use a combination of the constants
-     *              AppTransition.TRANSIT_FLAG_*.
-     * @param forceOverride Always override the transit, not matter what was set previously.
-     */
-    public void prepareAppTransition(@WindowManager.TransitionType int transit,
-            boolean alwaysKeepCurrent, @WindowManager.TransitionFlags int flags,
-            boolean forceOverride) {
-        synchronized (mGlobalLock) {
-            mRoot.getDisplayContent(mDisplayId).prepareAppTransition(transit, alwaysKeepCurrent,
-                    flags, forceOverride);
-        }
-    }
-
-    public void executeAppTransition() {
-        synchronized (mGlobalLock) {
-            mRoot.getDisplayContent(mDisplayId).executeAppTransition();
-        }
-    }
-
-    public void overridePendingAppTransition(String packageName,
-            int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
-        synchronized (mGlobalLock) {
-            mRoot.getDisplayContent(mDisplayId).mAppTransition.overridePendingAppTransition(
-                    packageName, enterAnim, exitAnim, startedCallback);
-        }
-    }
-
-    public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
-            int startHeight) {
-        synchronized (mGlobalLock) {
-            mRoot.getDisplayContent(mDisplayId).mAppTransition.overridePendingAppTransitionScaleUp(
-                    startX, startY, startWidth, startHeight);
-        }
-    }
-
-    public void overridePendingAppTransitionClipReveal(int startX, int startY,
-            int startWidth, int startHeight) {
-        synchronized (mGlobalLock) {
-            mRoot.getDisplayContent(mDisplayId)
-                    .mAppTransition.overridePendingAppTransitionClipReveal(startX, startY,
-                    startWidth, startHeight);
-        }
-    }
-
-    public void overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX,
-            int startY, IRemoteCallback startedCallback, boolean scaleUp) {
-        synchronized (mGlobalLock) {
-            mRoot.getDisplayContent(mDisplayId)
-                    .mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
-                    startedCallback, scaleUp);
-        }
-    }
-
-    public void overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX,
-            int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
-            boolean scaleUp) {
-        synchronized (mGlobalLock) {
-            mRoot.getDisplayContent(mDisplayId)
-                    .mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX,
-                    startY, targetWidth, targetHeight, startedCallback, scaleUp);
-        }
-    }
-
-    public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
-            IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback,
-            boolean scaleUp) {
-        synchronized (mGlobalLock) {
-            mRoot.getDisplayContent(mDisplayId)
-                    .mAppTransition.overridePendingAppTransitionMultiThumb(specs,
-                    onAnimationStartedCallback, onAnimationFinishedCallback, scaleUp);
-        }
-    }
-
-    public void overridePendingAppTransitionStartCrossProfileApps() {
-        synchronized (mGlobalLock) {
-            mRoot.getDisplayContent(mDisplayId)
-                    .mAppTransition.overridePendingAppTransitionStartCrossProfileApps();
-        }
-    }
-
-    public void overridePendingAppTransitionInPlace(String packageName, int anim) {
-        synchronized (mGlobalLock) {
-            mRoot.getDisplayContent(mDisplayId)
-                    .mAppTransition.overrideInPlaceAppTransition(packageName, anim);
-        }
-    }
-
-    /**
-     * Get Pending App transition of display.
-     *
-     * @return The pending app transition of the display.
-     */
-    public @TransitionType int getPendingAppTransition() {
-        synchronized (mGlobalLock) {
-            return mRoot.getDisplayContent(mDisplayId).mAppTransition.getAppTransition();
-        }
-    }
-
-    /**
-     * Check if pending app transition is for activity / task launch.
-     */
-    public boolean isNextTransitionForward() {
-        final int transit = getPendingAppTransition();
-        return transit == TRANSIT_ACTIVITY_OPEN
-                || transit == TRANSIT_TASK_OPEN
-                || transit == TRANSIT_TASK_TO_FRONT;
-    }
-
-    /**
-     * Checks if system decorations should be shown on this display.
-     *
-     * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
-     */
-    public boolean supportsSystemDecorations() {
-        synchronized (mGlobalLock) {
-            return mContainer.supportsSystemDecorations();
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "{DisplayWindowController displayId=" + mDisplayId + "}";
-    }
-}
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 4ef3513..5f56fe5 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -174,7 +174,7 @@
         mWindowManager.deferSurfaceLayout();
         try {
             setKeyguardGoingAway(true);
-            mRootActivityContainer.getDefaultDisplay().getWindowContainerController()
+            mRootActivityContainer.getDefaultDisplay().mDisplayContent
                     .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
                             false /* alwaysKeepCurrent */, convertTransitFlags(flags),
                             false /* forceOverride */);
@@ -302,7 +302,7 @@
         if (isKeyguardLocked()) {
             mWindowManager.deferSurfaceLayout();
             try {
-                mRootActivityContainer.getDefaultDisplay().getWindowContainerController()
+                mRootActivityContainer.getDefaultDisplay().mDisplayContent
                         .prepareAppTransition(resolveOccludeTransit(),
                                 false /* alwaysKeepCurrent */, 0 /* flags */,
                                 true /* forceOverride */);
@@ -332,11 +332,11 @@
 
         // If we are about to unocclude the Keyguard, but we can dismiss it without security,
         // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
-        final DisplayWindowController dwc =
-                mRootActivityContainer.getDefaultDisplay().getWindowContainerController();
+        final DisplayContent dc =
+                mRootActivityContainer.getDefaultDisplay().mDisplayContent;
         if (mKeyguardShowing && canDismissKeyguard()
-                && dwc.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
-            dwc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
+                && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
+            dc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
                     0 /* flags */, true /* forceOverride */);
             mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
             mWindowManager.executeAppTransition();
@@ -355,10 +355,10 @@
     }
 
     private int resolveOccludeTransit() {
-        final DisplayWindowController dwc =
-                mRootActivityContainer.getDefaultDisplay().getWindowContainerController();
+        final DisplayContent dc =
+                mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
         if (mBeforeUnoccludeTransit != TRANSIT_UNSET
-                && dwc.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
+                && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
                 // TODO(b/113840485): Handle app transition for individual display.
                 && isDisplayOccluded(DEFAULT_DISPLAY)) {
 
@@ -369,7 +369,7 @@
         } else if (!isDisplayOccluded(DEFAULT_DISPLAY)) {
 
             // Save transit in case we dismiss/occlude Keyguard shortly after.
-            mBeforeUnoccludeTransit = dwc.getPendingAppTransition();
+            mBeforeUnoccludeTransit = dc.mAppTransition.getAppTransition();
             return TRANSIT_KEYGUARD_UNOCCLUDE;
         } else {
             return TRANSIT_KEYGUARD_OCCLUDE;
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index d2f2863..3b66f7d 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -582,7 +582,7 @@
             mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities();
             final ActivityStack stack = task.getStack();
             if (stack != null) {
-                stack.getDisplay().getWindowContainerController().executeAppTransition();
+                stack.getDisplay().mDisplayContent.executeAppTransition();
             }
         } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
             mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 1e287b4..86fcf64 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -47,7 +47,7 @@
 
 import com.android.server.LocalServices;
 import com.android.server.am.AssistDataRequester;
-import com.android.server.intelligence.IntelligenceManagerInternal;
+import com.android.server.contentcapture.ContentCaptureManagerInternal;
 import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
 
 import java.util.List;
@@ -93,12 +93,12 @@
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "RecentsAnimation#startRecentsActivity");
 
         // TODO(multi-display) currently only support recents animation in default display.
-        final DisplayWindowController dwc =
-                mService.mRootActivityContainer.getDefaultDisplay().getWindowContainerController();
+        final DisplayContent dc =
+                mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
         if (!mWindowManager.canStartRecentsAnimation()) {
             notifyAnimationCancelBeforeStart(recentsAnimationRunner);
             if (DEBUG) Slog.d(TAG, "Can't start recents animation, nextAppTransition="
-                        + dwc.getPendingAppTransition());
+                        + dc.mAppTransition.getAppTransition());
             return;
         }
 
@@ -225,8 +225,8 @@
                 public void onAssistDataReceivedLocked(Bundle data, int activityIndex,
                         int activityCount) {
                     // Try to notify the intelligence service first
-                    final IntelligenceManagerInternal imService =
-                            LocalServices.getService(IntelligenceManagerInternal.class);
+                    final ContentCaptureManagerInternal imService =
+                            LocalServices.getService(ContentCaptureManagerInternal.class);
                     final IBinder activityToken = topActivities.get(activityIndex);
                     if (imService == null
                             || !imService.sendActivityAssistData(userId, activityToken, data)) {
@@ -236,8 +236,8 @@
                 }
             };
         } else {
-            final IntelligenceManagerInternal imService =
-                    LocalServices.getService(IntelligenceManagerInternal.class);
+            final ContentCaptureManagerInternal imService =
+                    LocalServices.getService(ContentCaptureManagerInternal.class);
             if (imService == null) {
                 // There is no intelligence service, so there is no point requesting assist data
                 return;
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 1d86b46..c5b42f9 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -864,7 +864,7 @@
             // Resize the pinned stack to match the current size of the task the activity we are
             // going to be moving is currently contained in. We do this to have the right starting
             // animation bounds for the pinned stack to the desired bounds the caller wants.
-            resizeStack(stack, task.getOverrideBounds(), null /* tempTaskBounds */,
+            resizeStack(stack, task.getRequestedOverrideBounds(), null /* tempTaskBounds */,
                     null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS,
                     true /* allowResizeInDockedMode */, !DEFER_RESUME);
 
@@ -914,7 +914,7 @@
     void executeAppTransitionForAllDisplay() {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            display.getWindowContainerController().executeAppTransition();
+            display.mDisplayContent.executeAppTransition();
         }
     }
 
@@ -1254,9 +1254,8 @@
     }
 
     // TODO: remove after object merge with RootWindowContainer
-    void onChildPositionChanged(DisplayWindowController childController, int position) {
+    void onChildPositionChanged(ActivityDisplay display, int position) {
         // Assume AM lock is held from positionChildAt of controller in each hierarchy.
-        final ActivityDisplay display = getActivityDisplay(childController.getDisplayId());
         if (display != null) {
             positionChildAt(display, position);
         }
@@ -1281,8 +1280,7 @@
     @VisibleForTesting
     void addChild(ActivityDisplay activityDisplay, int position) {
         positionChildAt(activityDisplay, position);
-        mRootWindowContainer.positionChildAt(position,
-                activityDisplay.getWindowContainerController().mContainer);
+        mRootWindowContainer.positionChildAt(position, activityDisplay.mDisplayContent);
     }
 
     void removeChild(ActivityDisplay activityDisplay) {
@@ -1297,7 +1295,7 @@
             throw new IllegalArgumentException("No display found with id: " + displayId);
         }
 
-        return activityDisplay.getOverrideConfiguration();
+        return activityDisplay.getRequestedOverrideConfiguration();
     }
 
     void setDisplayOverrideConfiguration(Configuration overrideConfiguration, int displayId) {
@@ -1306,7 +1304,7 @@
             throw new IllegalArgumentException("No display found with id: " + displayId);
         }
 
-        activityDisplay.onOverrideConfigurationChanged(overrideConfiguration);
+        activityDisplay.onRequestedOverrideConfigurationChanged(overrideConfiguration);
     }
 
     void prepareForShutdown() {
@@ -2161,7 +2159,7 @@
         for (int i = 0; i < displayCount; i++) {
             final ActivityDisplay activityDisplay = mActivityDisplays.get(i);
             pw.print(prefix); pw.print("  "); pw.print(activityDisplay.mDisplayId); pw.print(": ");
-            pw.println(activityDisplay.getOverrideConfiguration());
+            pw.println(activityDisplay.getRequestedOverrideConfiguration());
         }
     }
 
@@ -2190,7 +2188,7 @@
                         + ": type=" + activityTypeToString(stack.getActivityType())
                         + " mode=" + windowingModeToString(stack.getWindowingMode()));
                 pw.println("  isSleeping=" + stack.shouldSleepActivities());
-                pw.println("  mBounds=" + stack.getOverrideBounds());
+                pw.println("  mBounds=" + stack.getRequestedOverrideBounds());
 
                 printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage,
                         needSep);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index b98d154..3bbef92 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -224,7 +224,7 @@
         return null;
     }
 
-    DisplayContent createDisplayContent(final Display display, DisplayWindowController controller) {
+    DisplayContent createDisplayContent(final Display display, ActivityDisplay activityDisplay) {
         final int displayId = display.getDisplayId();
 
         // In select scenarios, it is possible that a DisplayContent will be created on demand
@@ -233,17 +233,17 @@
         final DisplayContent existing = getDisplayContent(displayId);
 
         if (existing != null) {
-            initializeDisplayOverrideConfiguration(controller, existing);
-            existing.setController(controller);
+            existing.mAcitvityDisplay = activityDisplay;
+            existing.initializeDisplayOverrideConfiguration();
             return existing;
         }
 
-        final DisplayContent dc = new DisplayContent(display, mWmService, controller);
+        final DisplayContent dc = new DisplayContent(display, mWmService, activityDisplay);
 
         if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
 
         mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(dc);
-        initializeDisplayOverrideConfiguration(controller, dc);
+        dc.initializeDisplayOverrideConfiguration();
 
         if (mWmService.mDisplayManagerInternal != null) {
             mWmService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
@@ -256,19 +256,6 @@
         return dc;
     }
 
-    /**
-     * The display content may have configuration set from {@link #DisplayWindowSettings}. This
-     * callback let the owner of container know there is existing configuration to prevent the
-     * values from being replaced by the initializing {@link #ActivityDisplay}.
-     */
-    private void initializeDisplayOverrideConfiguration(DisplayWindowController controller,
-            DisplayContent displayContent) {
-        if (controller != null && controller.mListener != null) {
-            controller.mListener.onInitializeOverrideConfiguration(
-                    displayContent.getOverrideConfiguration());
-        }
-    }
-
     boolean isLayoutNeeded() {
         final int numDisplays = mChildren.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
@@ -356,13 +343,13 @@
     void setDisplayOverrideConfigurationIfNeeded(Configuration newConfiguration,
             @NonNull DisplayContent displayContent) {
 
-        final Configuration currentConfig = displayContent.getOverrideConfiguration();
+        final Configuration currentConfig = displayContent.getRequestedOverrideConfiguration();
         final boolean configChanged = currentConfig.diff(newConfiguration) != 0;
         if (!configChanged) {
             return;
         }
 
-        displayContent.onOverrideConfigurationChanged(newConfiguration);
+        displayContent.onRequestedOverrideConfigurationChanged(newConfiguration);
 
         if (displayContent.getDisplayId() == DEFAULT_DISPLAY) {
             // Override configuration of the default display duplicates global config. In this case
@@ -1040,7 +1027,7 @@
     void positionChildAt(int position, DisplayContent child, boolean includingParents) {
         super.positionChildAt(position, child, includingParents);
         if (mRootActivityContainer != null) {
-            mRootActivityContainer.onChildPositionChanged(child.getController(), position);
+            mRootActivityContainer.onChildPositionChanged(child.mAcitvityDisplay, position);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c70f075..67657d0 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -119,7 +119,7 @@
         mResizeMode = resizeMode;
         mSupportsPictureInPicture = supportsPictureInPicture;
         setController(controller);
-        setBounds(getOverrideBounds());
+        setBounds(getRequestedOverrideBounds());
         mTaskDescription = taskDescription;
 
         // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
@@ -369,7 +369,7 @@
      *                    the adjusted bounds's top.
      */
     void alignToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds, boolean alignBottom) {
-        if (!isResizeable() || EMPTY.equals(getOverrideConfiguration())) {
+        if (!isResizeable() || EMPTY.equals(getRequestedOverrideConfiguration())) {
             return;
         }
 
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 3cf0bd7..b6a6009 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -506,7 +506,7 @@
             // If this is a forced resize, let it go through even if the bounds is not changing,
             // as we might need a relayout due to surface size change (to/from fullscreen).
             final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
-            if (equivalentOverrideBounds(bounds) && !forced) {
+            if (equivalentRequestedOverrideBounds(bounds) && !forced) {
                 // Nothing to do here...
                 return true;
             }
@@ -720,12 +720,12 @@
             // Make sure the task has the appropriate bounds/size for the stack it is in.
             final boolean toStackSplitScreenPrimary =
                     toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-            final Rect configBounds = getOverrideBounds();
+            final Rect configBounds = getRequestedOverrideBounds();
             if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
                     || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
-                    && !Objects.equals(configBounds, toStack.getOverrideBounds())) {
-                kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
-                        deferResume);
+                    && !Objects.equals(configBounds, toStack.getRequestedOverrideBounds())) {
+                kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
+                        !mightReplaceWindow, deferResume);
             } else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
                 Rect bounds = getLaunchBounds();
                 if (bounds == null) {
@@ -739,8 +739,8 @@
                     // mode
                     mService.mStackSupervisor.moveRecentsStackToFront(reason);
                 }
-                kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
-                        deferResume);
+                kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
+                        !mightReplaceWindow, deferResume);
             }
         } finally {
             windowManager.continueSurfaceLayout();
@@ -1546,7 +1546,7 @@
             return true;
         }
         final boolean landscape = bounds.width() > bounds.height();
-        final Rect configBounds = getOverrideBounds();
+        final Rect configBounds = getRequestedOverrideBounds();
         if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
             return configBounds.isEmpty()
                     || landscape == (configBounds.width() > configBounds.height());
@@ -1709,7 +1709,7 @@
             return;
         }
 
-        final Rect configBounds = getOverrideBounds();
+        final Rect configBounds = getRequestedOverrideBounds();
         if (adjustWidth) {
             if (!configBounds.isEmpty() && bounds.right == configBounds.right) {
                 bounds.left = bounds.right - minWidth;
@@ -1739,7 +1739,7 @@
         // (bounds == null), then leave the override config unset
         final Configuration newOverrideConfig = new Configuration();
         if (bounds != null) {
-            newOverrideConfig.setTo(getOverrideConfiguration());
+            newOverrideConfig.setTo(getRequestedOverrideConfiguration());
             if (insetBounds != null && !insetBounds.isEmpty()) {
                 mTmpRect.set(insetBounds);
                 setDisplayedBounds(bounds);
@@ -1781,13 +1781,13 @@
      * @return True if the override configuration was updated.
      */
     boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
-        if (equivalentOverrideBounds(bounds)) {
+        if (equivalentRequestedOverrideBounds(bounds)) {
             return false;
         }
-        final Rect currentBounds = getOverrideBounds();
+        final Rect currentBounds = getRequestedOverrideBounds();
 
-        mTmpConfig.setTo(getOverrideConfiguration());
-        final Configuration newConfig = getOverrideConfiguration();
+        mTmpConfig.setTo(getRequestedOverrideConfiguration());
+        final Configuration newConfig = getRequestedOverrideConfiguration();
 
         final boolean matchParentBounds = bounds == null || bounds.isEmpty();
         final boolean persistBounds = getWindowConfiguration().persistTaskBounds();
@@ -1810,12 +1810,12 @@
             setBounds(mTmpRect);
 
             if (mStack == null || persistBounds) {
-                setLastNonFullscreenBounds(getOverrideBounds());
+                setLastNonFullscreenBounds(getRequestedOverrideBounds());
             }
             computeOverrideConfiguration(newConfig, mTmpRect,
                     mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
         }
-        onOverrideConfigurationChanged(newConfig);
+        onRequestedOverrideConfigurationChanged(newConfig);
         return !mTmpConfig.equals(newConfig);
     }
 
@@ -1949,7 +1949,7 @@
         if (bounds != null && !bounds.isEmpty()) {
             // TODO: Review if we actually want to do this - we are setting the launch bounds
             // directly here.
-            bounds.set(getOverrideBounds());
+            bounds.set(getRequestedOverrideBounds());
         }
         return bounds;
     }
@@ -1975,7 +1975,7 @@
                 mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
             }
         } else {
-            updateOverrideConfiguration(inStack.getOverrideBounds());
+            updateOverrideConfiguration(inStack.getRequestedOverrideBounds());
         }
     }
 
@@ -1989,9 +1989,9 @@
         if (!isActivityTypeStandardOrUndefined()
                 || windowingMode == WINDOWING_MODE_FULLSCREEN
                 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
-            return isResizeable() ? mStack.getOverrideBounds() : null;
+            return isResizeable() ? mStack.getRequestedOverrideBounds() : null;
         } else if (!getWindowConfiguration().persistTaskBounds()) {
-            return mStack.getOverrideBounds();
+            return mStack.getRequestedOverrideBounds();
         }
         return mLastNonFullscreenBounds;
     }
@@ -2210,7 +2210,7 @@
         proto.write(FULLSCREEN, matchParentBounds());
 
         if (!matchParentBounds()) {
-            final Rect bounds = getOverrideBounds();
+            final Rect bounds = getRequestedOverrideBounds();
             bounds.writeToProto(proto, BOUNDS);
         }
         proto.write(MIN_WIDTH, mMinWidth);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index b16e184c..11d9ebb 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -282,7 +282,7 @@
 
     @Override
     public int setBounds(Rect bounds) {
-        return setBounds(getOverrideBounds(), bounds);
+        return setBounds(getRequestedOverrideBounds(), bounds);
     }
 
     private int setBounds(Rect existing, Rect bounds) {
@@ -304,8 +304,8 @@
 
     /** Bounds of the stack without adjusting for other factors in the system like visibility
      * of docked stack.
-     * Most callers should be using {@link ConfigurationContainer#getOverrideBounds} as it take into
-     * consideration other system factors. */
+     * Most callers should be using {@link ConfigurationContainer#getRequestedOverrideBounds} a
+     * it takes into consideration other system factors. */
     void getRawBounds(Rect out) {
         out.set(getRawBounds());
     }
@@ -448,7 +448,8 @@
      * @param inOutBounds the bounds to update (both input and output).
      */
     void calculateDockedBoundsForConfigChange(Configuration parentConfig, Rect inOutBounds) {
-        final boolean primary = getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+        final boolean primary =
+                getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
         repositionSplitScreenStackAfterRotation(parentConfig, primary, inOutBounds);
         final DisplayCutout cutout = mDisplayContent.getDisplayInfo().displayCutout;
         snapDockedStackAfterRotation(parentConfig, cutout, inOutBounds);
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
index ec64d2e..b87b65e 100644
--- a/services/core/java/com/android/server/wm/TaskWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
@@ -157,7 +157,8 @@
                 throw new IllegalArgumentException("resizeTask: taskId " + mTaskId + " not found.");
             }
 
-            if (mContainer.setBounds(mContainer.getOverrideBounds(), forced) != BOUNDS_CHANGE_NONE
+            if (mContainer.setBounds(
+                    mContainer.getRequestedOverrideBounds(), forced) != BOUNDS_CHANGE_NONE
                     && relayout) {
                 mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
             }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index c30cc17..651089d 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -469,15 +469,16 @@
 
     /**
      * Update override configuration and recalculate full config.
-     * @see #mOverrideConfiguration
+     * @see #mRequestedOverrideConfiguration
      * @see #mFullConfiguration
      */
     @Override
-    public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+    public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
         // We must diff before the configuration is applied so that we can capture the change
         // against the existing bounds.
-        final int diff = diffOverrideBounds(overrideConfiguration.windowConfiguration.getBounds());
-        super.onOverrideConfigurationChanged(overrideConfiguration);
+        final int diff = diffRequestedOverrideBounds(
+                overrideConfiguration.windowConfiguration.getBounds());
+        super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
         if (mParent != null) {
             mParent.onDescendantOverrideConfigurationChanged();
         }
diff --git a/services/core/java/com/android/server/wm/WindowContainerController.java b/services/core/java/com/android/server/wm/WindowContainerController.java
index 7cb89c5..17bc0e2 100644
--- a/services/core/java/com/android/server/wm/WindowContainerController.java
+++ b/services/core/java/com/android/server/wm/WindowContainerController.java
@@ -72,12 +72,12 @@
     }
 
     @Override
-    public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+    public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
         synchronized (mGlobalLock) {
             if (mContainer == null) {
                 return;
             }
-            mContainer.onOverrideConfigurationChanged(overrideConfiguration);
+            mContainer.onRequestedOverrideConfigurationChanged(overrideConfiguration);
         }
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 2dec4dd..f7f7528 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -770,8 +770,8 @@
     }
 
     @Override
-    public void onOverrideConfigurationChanged(Configuration newOverrideConfig) {
-        super.onOverrideConfigurationChanged(newOverrideConfig);
+    public void onRequestedOverrideConfigurationChanged(Configuration newOverrideConfig) {
+        super.onRequestedOverrideConfigurationChanged(newOverrideConfig);
         updateConfiguration();
     }
 
@@ -924,7 +924,7 @@
             }
         }
         pw.println(prefix + " Configuration=" + getConfiguration());
-        pw.println(prefix + " OverrideConfiguration=" + getOverrideConfiguration());
+        pw.println(prefix + " OverrideConfiguration=" + getRequestedOverrideConfiguration());
         pw.println(prefix + " mLastReportedConfiguration=" + mLastReportedConfiguration);
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e115fed..d2dfa76 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2836,6 +2836,7 @@
                 break;
             }
         }
+        cropRegionToStackBoundsIfNeeded(outRegion);
 
         if (forSurface) {
             if (mTouchableInsets != TOUCHABLE_INSETS_REGION) {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index b85489a..6d72191 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -126,7 +126,6 @@
 
     static_libs: [
         "android.hardware.broadcastradio@common-utils-1x-lib",
-        "libscrypt_static",
     ],
 
     product_variables: {
diff --git a/services/core/jni/com_android_server_locksettings_SyntheticPasswordManager.cpp b/services/core/jni/com_android_server_locksettings_SyntheticPasswordManager.cpp
index bc13fde..9dd6032 100644
--- a/services/core/jni/com_android_server_locksettings_SyntheticPasswordManager.cpp
+++ b/services/core/jni/com_android_server_locksettings_SyntheticPasswordManager.cpp
@@ -27,10 +27,6 @@
 #include <gatekeeper/password_handle.h>
 
 
-extern "C" {
-#include "crypto_scrypt.h"
-}
-
 namespace android {
 
 static jlong android_server_SyntheticPasswordManager_nativeSidFromPasswordHandle(JNIEnv* env, jobject, jbyteArray handleArray) {
@@ -48,38 +44,9 @@
     }
 }
 
-static jbyteArray android_server_SyntheticPasswordManager_nativeScrypt(JNIEnv* env, jobject, jbyteArray password, jbyteArray salt, jint N, jint r, jint p, jint outLen) {
-    if (!password || !salt) {
-        return NULL;
-    }
-
-    int passwordLen = env->GetArrayLength(password);
-    int saltLen = env->GetArrayLength(salt);
-    jbyteArray ret = env->NewByteArray(outLen);
-
-    jbyte* passwordPtr = (jbyte*)env->GetByteArrayElements(password, NULL);
-    jbyte* saltPtr = (jbyte*)env->GetByteArrayElements(salt, NULL);
-    jbyte* retPtr = (jbyte*)env->GetByteArrayElements(ret, NULL);
-
-    int rc = crypto_scrypt((const uint8_t *)passwordPtr, passwordLen,
-                       (const uint8_t *)saltPtr, saltLen, N, r, p, (uint8_t *)retPtr,
-                       outLen);
-    env->ReleaseByteArrayElements(password, passwordPtr, JNI_ABORT);
-    env->ReleaseByteArrayElements(salt, saltPtr, JNI_ABORT);
-    env->ReleaseByteArrayElements(ret, retPtr, 0);
-
-    if (!rc) {
-        return ret;
-    } else {
-        SLOGE("scrypt failed");
-        return NULL;
-    }
-}
-
 static const JNINativeMethod sMethods[] = {
      /* name, signature, funcPtr */
     {"nativeSidFromPasswordHandle", "([B)J", (void*)android_server_SyntheticPasswordManager_nativeSidFromPasswordHandle},
-    {"nativeScrypt", "([B[BIIII)[B", (void*)android_server_SyntheticPasswordManager_nativeScrypt},
 };
 
 int register_android_server_SyntheticPasswordManager(JNIEnv* env) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 65d3245..c44f306 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -81,7 +81,8 @@
     }
 
     @Override
-    public void setGlobalPrivateDns(ComponentName who, int mode, String privateDnsHost) {
+    public int setGlobalPrivateDns(ComponentName who, int mode, String privateDnsHost) {
+        return DevicePolicyManager.PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
     }
 
     @Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a7dbdcb..bfbaac9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -59,6 +59,8 @@
 import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
 import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
 import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_MODE_UNKNOWN;
+import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
+import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_SET_SUCCESS;
 import static android.app.admin.DevicePolicyManager.PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
 import static android.app.admin.DevicePolicyManager.WIPE_EUICC;
 import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
@@ -4932,14 +4934,16 @@
     private boolean resetPasswordInternal(String password, long tokenHandle, byte[] token,
             int flags, int callingUid, int userHandle) {
         int quality;
+        final int realQuality;
         synchronized (getLockObject()) {
             quality = getPasswordQuality(null, userHandle, /* parent */ false);
             if (quality == DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
                 quality = PASSWORD_QUALITY_UNSPECIFIED;
             }
             final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password);
+            realQuality = metrics.quality;
             if (quality != PASSWORD_QUALITY_UNSPECIFIED) {
-                final int realQuality = metrics.quality;
+
                 if (realQuality < quality
                         && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
                     Slog.w(LOG_TAG, "resetPassword: password quality 0x"
@@ -5026,7 +5030,7 @@
         try {
             if (token == null) {
                 if (!TextUtils.isEmpty(password)) {
-                    mLockPatternUtils.saveLockPassword(password, null, quality, userHandle);
+                    mLockPatternUtils.saveLockPassword(password, null, realQuality, userHandle);
                 } else {
                     mLockPatternUtils.clearLock(null, userHandle);
                 }
@@ -5035,7 +5039,7 @@
                 result = mLockPatternUtils.setLockCredentialWithToken(password,
                         TextUtils.isEmpty(password) ? LockPatternUtils.CREDENTIAL_TYPE_NONE
                                 : LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                                quality, tokenHandle, token, userHandle);
+                        realQuality, tokenHandle, token, userHandle);
             }
             boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
             if (requireEntry) {
@@ -13396,32 +13400,40 @@
     }
 
     @Override
-    public void setGlobalPrivateDns(@NonNull ComponentName who, int mode, String privateDnsHost) {
+    public int setGlobalPrivateDns(@NonNull ComponentName who, int mode, String privateDnsHost) {
         if (!mHasFeature) {
-            return;
+            return PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
         }
 
         Preconditions.checkNotNull(who, "ComponentName is null");
         enforceDeviceOwner(who);
 
+        final int returnCode;
+
         switch (mode) {
             case PRIVATE_DNS_MODE_OPPORTUNISTIC:
                 if (!TextUtils.isEmpty(privateDnsHost)) {
-                    throw new IllegalArgumentException("A DNS host should not be provided when " +
-                            "setting opportunistic mode.");
+                    throw new IllegalArgumentException(
+                            "Host provided for opportunistic mode, but is not needed.");
                 }
                 putPrivateDnsSettings(ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC, null);
-                break;
+                return PRIVATE_DNS_SET_SUCCESS;
             case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME:
-                if (!NetworkUtils.isWeaklyValidatedHostname(privateDnsHost)) {
+                if (TextUtils.isEmpty(privateDnsHost)
+                        || !NetworkUtils.isWeaklyValidatedHostname(privateDnsHost)) {
                     throw new IllegalArgumentException(
-                            String.format("Provided hostname is not valid: %s", privateDnsHost));
+                            String.format("Provided hostname %s is not valid", privateDnsHost));
                 }
-                putPrivateDnsSettings(ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME,
+
+                // Connectivity check will have been performed in the DevicePolicyManager before
+                // the call here.
+                putPrivateDnsSettings(
+                        ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME,
                         privateDnsHost);
-                break;
+                return PRIVATE_DNS_SET_SUCCESS;
             default:
-                throw new IllegalArgumentException(String.format("Unsupported mode: %d", mode));
+                throw new IllegalArgumentException(
+                        String.format("Provided mode, %d, is not a valid mode.", mode));
         }
     }
 
diff --git a/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java b/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
deleted file mode 100644
index c4fbdca..0000000
--- a/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
+++ /dev/null
@@ -1,280 +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.server.intelligence;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.service.intelligence.ContentCaptureEventsRequest;
-import android.service.intelligence.IIntelligenceService;
-import android.service.intelligence.InteractionContext;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.SnapshotData;
-import android.text.format.DateUtils;
-import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillManager;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-
-import com.android.internal.os.IResultReceiver;
-import com.android.server.infra.AbstractMultiplePendingRequestsRemoteService;
-
-import java.util.List;
-
-//TODO(b/111276913): rename once the final name is defined
-final class RemoteIntelligenceService
-        extends AbstractMultiplePendingRequestsRemoteService<RemoteIntelligenceService> {
-
-    private static final String TAG = "RemoteIntelligenceService";
-
-    private static final long TIMEOUT_IDLE_BIND_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
-    private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
-
-    private final RemoteIntelligenceServiceCallbacks mCallbacks;
-    private IIntelligenceService mService;
-
-    RemoteIntelligenceService(Context context, String serviceInterface,
-            ComponentName componentName, int userId,
-            RemoteIntelligenceServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
-            boolean verbose) {
-        super(context, serviceInterface, componentName, userId, callbacks,
-                bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2);
-        mCallbacks = callbacks;
-    }
-
-    @Override // from RemoteService
-    protected IInterface getServiceInterface(@NonNull IBinder service) {
-        mService = IIntelligenceService.Stub.asInterface(service);
-        return mService;
-    }
-
-    // TODO(b/111276913): modify super class to allow permanent binding when value is 0 or negative
-    @Override // from RemoteService
-    protected long getTimeoutIdleBindMillis() {
-        // TODO(b/111276913): read from Settings so it can be changed in the field
-        return TIMEOUT_IDLE_BIND_MILLIS;
-    }
-
-    @Override // from RemoteService
-    protected long getRemoteRequestMillis() {
-        // TODO(b/111276913): read from Settings so it can be changed in the field
-        return TIMEOUT_REMOTE_REQUEST_MILLIS;
-    }
-
-    /**
-     * Called by {@link ContentCaptureSession} to generate a call to the
-     * {@link RemoteIntelligenceService} to indicate the session was created (when {@code context}
-     * is not {@code null} or destroyed (when {@code context} is {@code null}).
-     */
-    public void onSessionLifecycleRequest(@Nullable InteractionContext context,
-            @NonNull InteractionSessionId sessionId) {
-        cancelScheduledUnbind();
-        scheduleRequest(new PendingSessionLifecycleRequest(this, context, sessionId));
-    }
-
-    /**
-     * Called by {@link ContentCaptureSession} to send a batch of events to the service.
-     */
-    public void onContentCaptureEventsRequest(@NonNull InteractionSessionId sessionId,
-            @NonNull List<ContentCaptureEvent> events) {
-        cancelScheduledUnbind();
-        scheduleRequest(new PendingOnContentCaptureEventsRequest(this, sessionId, events));
-    }
-
-    /**
-     * Called by {@link ContentCaptureSession} to send snapshot data to the service.
-     */
-    public void onActivitySnapshotRequest(@NonNull InteractionSessionId sessionId,
-            @NonNull SnapshotData snapshotData) {
-        cancelScheduledUnbind();
-        scheduleRequest(new PendingOnActivitySnapshotRequest(this, sessionId, snapshotData));
-    }
-
-    /**
-     * Called by {@link ContentCaptureSession} to request augmented autofill.
-     */
-    public void onRequestAutofillLocked(@NonNull InteractionSessionId sessionId,
-            @NonNull IAutoFillManagerClient client, int autofillSessionId,
-            @NonNull AutofillId focusedId, @Nullable AutofillValue focusedValue) {
-        cancelScheduledUnbind();
-        scheduleRequest(new PendingAutofillRequest(this, sessionId, client, autofillSessionId,
-                focusedId, focusedValue));
-    }
-
-    /**
-     * Called by {@link ContentCaptureSession} when it's time to destroy all augmented autofill
-     * requests.
-     */
-    public void onDestroyAutofillWindowsRequest(@NonNull InteractionSessionId sessionId) {
-        cancelScheduledUnbind();
-        scheduleRequest(new PendingDestroyAutofillWindowsRequest(this, sessionId));
-    }
-
-    private abstract static class MyPendingRequest
-            extends PendingRequest<RemoteIntelligenceService> {
-        protected final InteractionSessionId mSessionId;
-
-        private MyPendingRequest(@NonNull RemoteIntelligenceService service,
-                @NonNull InteractionSessionId sessionId) {
-            super(service);
-            mSessionId = sessionId;
-        }
-
-        @Override // from PendingRequest
-        protected final void onTimeout(RemoteIntelligenceService remoteService) {
-            Slog.w(TAG, "timed out handling " + getClass().getSimpleName() + " for "
-                    + mSessionId);
-            remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ true);
-        }
-
-        @Override // from PendingRequest
-        public final void run() {
-            final RemoteIntelligenceService remoteService = getService();
-            if (remoteService != null) {
-                try {
-                    // We don't expect the service to call us back, so we finish right away.
-                    myRun(remoteService);
-                    // TODO(b/111330312): not true anymore!!
-                    finish();
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "exception handling " + getClass().getSimpleName() + " for "
-                            + mSessionId + ": " + e);
-                    remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ false);
-                }
-            }
-        }
-
-        protected abstract void myRun(@NonNull RemoteIntelligenceService service)
-                throws RemoteException;
-
-    }
-
-    private static final class PendingSessionLifecycleRequest extends MyPendingRequest {
-
-        private final InteractionContext mContext;
-
-        protected PendingSessionLifecycleRequest(@NonNull RemoteIntelligenceService service,
-                @Nullable InteractionContext context, @NonNull InteractionSessionId sessionId) {
-            super(service, sessionId);
-            mContext = context;
-        }
-
-        @Override // from MyPendingRequest
-        public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
-            remoteService.mService.onSessionLifecycle(mContext, mSessionId);
-        }
-    }
-
-    private static final class PendingOnContentCaptureEventsRequest extends MyPendingRequest {
-
-        private final List<ContentCaptureEvent> mEvents;
-
-        protected PendingOnContentCaptureEventsRequest(@NonNull RemoteIntelligenceService service,
-                @NonNull InteractionSessionId sessionId,
-                @NonNull List<ContentCaptureEvent> events) {
-            super(service, sessionId);
-            mEvents = events;
-        }
-
-        @Override // from MyPendingRequest
-        public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
-            remoteService.mService.onContentCaptureEventsRequest(mSessionId,
-                    new ContentCaptureEventsRequest(mEvents));
-        }
-    }
-
-    private static final class PendingOnActivitySnapshotRequest extends MyPendingRequest {
-
-        private final SnapshotData mSnapshotData;
-
-        protected PendingOnActivitySnapshotRequest(@NonNull RemoteIntelligenceService service,
-                @NonNull InteractionSessionId sessionId,
-                @NonNull SnapshotData snapshotData) {
-            super(service, sessionId);
-            mSnapshotData = snapshotData;
-        }
-
-        @Override // from MyPendingRequest
-        protected void myRun(@NonNull RemoteIntelligenceService remoteService)
-                throws RemoteException {
-            remoteService.mService.onActivitySnapshot(mSessionId, mSnapshotData);
-        }
-    }
-
-    private static final class PendingAutofillRequest extends MyPendingRequest {
-        private final @NonNull AutofillId mFocusedId;
-        private final @Nullable AutofillValue mFocusedValue;
-        private final @NonNull IAutoFillManagerClient mClient;
-        private final int mAutofillSessionId;
-        private final long mRequestTime = SystemClock.elapsedRealtime();
-
-        protected PendingAutofillRequest(@NonNull RemoteIntelligenceService service,
-                @NonNull InteractionSessionId sessionId, @NonNull IAutoFillManagerClient client,
-                int autofillSessionId, @NonNull AutofillId focusedId,
-                @Nullable AutofillValue focusedValue) {
-            super(service, sessionId);
-            mClient = client;
-            mAutofillSessionId = autofillSessionId;
-            mFocusedId = focusedId;
-            mFocusedValue = focusedValue;
-        }
-
-        @Override // from MyPendingRequest
-        public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
-            final IResultReceiver receiver = new IResultReceiver.Stub() {
-
-                @Override
-                public void send(int resultCode, Bundle resultData) throws RemoteException {
-                    final IBinder realClient = resultData
-                            .getBinder(AutofillManager.EXTRA_AUGMENTED_AUTOFILL_CLIENT);
-                    remoteService.mService.onAutofillRequest(mSessionId, realClient,
-                            mAutofillSessionId, mFocusedId, mFocusedValue, mRequestTime);
-                }
-            };
-
-            // TODO(b/111330312): set cancellation signal, timeout (from  both mClient and service),
-            // cache IAugmentedAutofillManagerClient reference, etc...
-            mClient.getAugmentedAutofillClient(receiver);
-        }
-    }
-
-    private static final class PendingDestroyAutofillWindowsRequest extends MyPendingRequest {
-
-        protected PendingDestroyAutofillWindowsRequest(@NonNull RemoteIntelligenceService service,
-                @NonNull InteractionSessionId sessionId) {
-            super(service, sessionId);
-        }
-
-        @Override
-        protected void myRun(@NonNull RemoteIntelligenceService service) throws RemoteException {
-            service.mService.onDestroyAutofillWindowsRequest(mSessionId);
-            // TODO(b/111330312): implement timeout
-        }
-    }
-
-    public interface RemoteIntelligenceServiceCallbacks extends VultureCallback {
-        // To keep it simple, we use the same callback for all failures / timeouts.
-        void onFailureOrTimeout(boolean timedOut);
-    }
-}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c4d2a91..2baef6af 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -239,8 +239,8 @@
             "com.android.server.wallpaper.WallpaperManagerService$Lifecycle";
     private static final String AUTO_FILL_MANAGER_SERVICE_CLASS =
             "com.android.server.autofill.AutofillManagerService";
-    private static final String INTELLIGENCE_MANAGER_SERVICE_CLASS =
-            "com.android.server.intelligence.IntelligenceManagerService";
+    private static final String CONTENT_CAPTURE_MANAGER_SERVICE_CLASS =
+            "com.android.server.contentcapture.ContentCaptureManagerService";
     private static final String TIME_ZONE_RULES_MANAGER_SERVICE_CLASS =
             "com.android.server.timezone.RulesManagerService$Lifecycle";
     private static final String IOT_SERVICE_CLASS =
@@ -1136,7 +1136,7 @@
                 traceEnd();
             }
 
-            startIntelligenceService(context);
+            startContentCaptureService(context);
 
             // NOTE: ClipboardService indirectly depends on IntelligenceService
             traceBeginAndSlog("StartClipboardService");
@@ -1398,6 +1398,15 @@
                 traceEnd();
             }
 
+            // Start ADB Debugging Service
+            traceBeginAndSlog("StartAdbService");
+            try {
+                mSystemServiceManager.startService(ADB_SERVICE_CLASS);
+            } catch (Throwable e) {
+                Slog.e(TAG, "Failure starting AdbService");
+            }
+            traceEnd();
+
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)
                     || mPackageManager.hasSystemFeature(
                     PackageManager.FEATURE_USB_ACCESSORY)
@@ -1408,15 +1417,6 @@
                 traceEnd();
             }
 
-            // Start ADB Debugging Service
-            traceBeginAndSlog("StartAdbService");
-            try {
-                mSystemServiceManager.startService(ADB_SERVICE_CLASS);
-            } catch (Throwable e) {
-                Slog.e(TAG, "Failure starting AdbService");
-            }
-            traceEnd();
-
             if (!isWatch) {
                 traceBeginAndSlog("StartSerialService");
                 try {
@@ -2100,18 +2100,18 @@
         }, BOOT_TIMINGS_TRACE_LOG);
     }
 
-    private void startIntelligenceService(@NonNull Context context) {
+    private void startContentCaptureService(@NonNull Context context) {
 
         // First check if it was explicitly enabled by Settings
         boolean explicitlySupported = false;
         final String settings = Settings.Global.getString(context.getContentResolver(),
-                Settings.Global.SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED);
+                Settings.Global.CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED);
         if (settings != null) {
             explicitlySupported = Boolean.parseBoolean(settings);
             if (explicitlySupported) {
-                Slog.d(TAG, "IntelligenceService explicitly enabled by Settings");
+                Slog.d(TAG, "ContentCaptureService explicitly enabled by Settings");
             } else {
-                Slog.d(TAG, "IntelligenceService explicitly disabled by Settings");
+                Slog.d(TAG, "ContentCaptureService explicitly disabled by Settings");
                 return;
             }
         }
@@ -2119,15 +2119,15 @@
         // Then check if OEM overlaid the resource that defines the service.
         if (!explicitlySupported) {
             final String serviceName = context
-                    .getString(com.android.internal.R.string.config_defaultSmartSuggestionsService);
+                    .getString(com.android.internal.R.string.config_defaultContentCaptureService);
             if (TextUtils.isEmpty(serviceName)) {
-                Slog.d(TAG, "IntelligenceService disabled because config resource is not overlaid");
+                Slog.d(TAG, "ContentCaptureService disabled because resource is not overlaid");
                 return;
             }
         }
 
-        traceBeginAndSlog("StartIntelligenceService");
-        mSystemServiceManager.startService(INTELLIGENCE_MANAGER_SERVICE_CLASS);
+        traceBeginAndSlog("StartContentCaptureService");
+        mSystemServiceManager.startService(CONTENT_CAPTURE_MANAGER_SERVICE_CLASS);
         traceEnd();
     }
 
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index ba4caf44..b01adc9 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -57,7 +57,6 @@
     private static final String TEST_TRANSPORT = "transport";
 
     @Mock private UserBackupManagerService mUserBackupManagerService;
-    @Mock private TransportManager mTransportManager;
     private BackupManagerService mBackupManagerService;
     private Context mContext;
 
@@ -72,10 +71,7 @@
                 new BackupManagerService(
                         application,
                         new Trampoline(application),
-                        BackupManagerServiceTestUtils.startBackupThread(null),
-                        new File(application.getCacheDir(), "base_state"),
-                        new File(application.getCacheDir(), "data"),
-                        mTransportManager);
+                        BackupManagerServiceTestUtils.startBackupThread(null));
         mBackupManagerService.setUserBackupManagerService(mUserBackupManagerService);
     }
 
diff --git a/services/robotests/src/com/android/server/backup/UserBackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/UserBackupManagerServiceTest.java
index 9d43819..efbcb96 100644
--- a/services/robotests/src/com/android/server/backup/UserBackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/UserBackupManagerServiceTest.java
@@ -148,7 +148,7 @@
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName)))
                 .thenReturn("destinationString");
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         String destination = backupManagerService.getDestinationString(mTransportName);
 
@@ -164,7 +164,7 @@
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName)))
                 .thenThrow(TransportNotRegisteredException.class);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         String destination = backupManagerService.getDestinationString(mTransportName);
 
@@ -180,7 +180,7 @@
         mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
         when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName)))
                 .thenThrow(TransportNotRegisteredException.class);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
                 SecurityException.class,
@@ -195,7 +195,7 @@
     public void testIsAppEligibleForBackup_whenAppNotEligible() throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         setUpCurrentTransport(mTransportManager, mTransport);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         boolean result = backupManagerService.isAppEligibleForBackup(PACKAGE_1);
 
@@ -211,7 +211,7 @@
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         TransportMock transportMock = setUpCurrentTransport(mTransportManager, backupTransport());
         ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(PACKAGE_1);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         boolean result = backupManagerService.isAppEligibleForBackup(PACKAGE_1);
 
@@ -229,7 +229,7 @@
         mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
         setUpCurrentTransport(mTransportManager, mTransport);
         ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(PACKAGE_1);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
                 SecurityException.class,
@@ -246,7 +246,7 @@
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         TransportMock transportMock = setUpCurrentTransport(mTransportManager, mTransport);
         ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(PACKAGE_1);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         String[] filtered =
                 backupManagerService.filterAppsEligibleForBackup(
@@ -264,7 +264,7 @@
     @Test
     public void testFilterAppsEligibleForBackup_whenNoneIsEligible() throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         String[] filtered =
                 backupManagerService.filterAppsEligibleForBackup(
@@ -281,7 +281,7 @@
     public void testFilterAppsEligibleForBackup_withoutPermission() throws Exception {
         mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
         setUpCurrentTransport(mTransportManager, mTransport);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
                 SecurityException.class,
@@ -319,7 +319,7 @@
     public void testSelectBackupTransport() throws Exception {
         setUpForSelectTransport();
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         String oldTransport =
                 backupManagerService.selectBackupTransport(mNewTransport.transportName);
@@ -338,7 +338,7 @@
     public void testSelectBackupTransport_withoutPermission() throws Exception {
         setUpForSelectTransport();
         mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
                 SecurityException.class,
@@ -356,7 +356,7 @@
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
                 .thenReturn(BackupManager.SUCCESS);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
         ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
 
         backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
@@ -380,7 +380,7 @@
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
                 .thenReturn(BackupManager.ERROR_TRANSPORT_UNAVAILABLE);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
         ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
 
         backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
@@ -402,7 +402,7 @@
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         when(mTransportManager.registerAndSelectTransport(eq(newTransportComponent)))
                 .thenReturn(BackupManager.SUCCESS);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
         ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
 
         backupManagerService.selectBackupTransportAsync(newTransportComponent, callback);
@@ -421,7 +421,7 @@
     public void testSelectBackupTransportAsync_withoutPermission() throws Exception {
         setUpForSelectTransport();
         mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
         ComponentName newTransportComponent = mNewTransport.getTransportComponent();
 
         expectThrows(
@@ -445,7 +445,7 @@
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         when(mTransportManager.getCurrentTransportComponent())
                 .thenReturn(mTransport.getTransportComponent());
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         ComponentName transportComponent = backupManagerService.getCurrentTransportComponent();
 
@@ -460,7 +460,7 @@
     public void testGetCurrentTransportComponent_whenNoTransportSelected() throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         when(mTransportManager.getCurrentTransportComponent()).thenReturn(null);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         ComponentName transportComponent = backupManagerService.getCurrentTransportComponent();
 
@@ -476,7 +476,7 @@
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         when(mTransportManager.getCurrentTransportComponent())
                 .thenThrow(TransportNotRegisteredException.class);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         ComponentName transportComponent = backupManagerService.getCurrentTransportComponent();
 
@@ -490,7 +490,7 @@
     @Test
     public void testGetCurrentTransportComponent_withoutPermission() throws Exception {
         mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(SecurityException.class, backupManagerService::getCurrentTransportComponent);
     }
@@ -525,7 +525,7 @@
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         Intent configurationIntent = new Intent();
         Intent dataManagementIntent = new Intent();
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         backupManagerService.updateTransportAttributes(
                 mTransportUid,
@@ -556,7 +556,7 @@
             throws Exception {
         setUpForUpdateTransportAttributes();
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
                 SecurityException.class,
@@ -581,7 +581,7 @@
             throws Exception {
         setUpForUpdateTransportAttributes();
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
                 RuntimeException.class,
@@ -605,7 +605,7 @@
     public void testUpdateTransportAttributes_whenNameNull_throwsException() throws Exception {
         setUpForUpdateTransportAttributes();
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
                 RuntimeException.class,
@@ -630,7 +630,7 @@
             throws Exception {
         setUpForUpdateTransportAttributes();
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
                 RuntimeException.class,
@@ -657,7 +657,7 @@
                     throws Exception {
         setUpForUpdateTransportAttributes();
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
                 RuntimeException.class,
@@ -696,7 +696,7 @@
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         Intent configurationIntent = new Intent();
         Intent dataManagementIntent = new Intent();
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         backupManagerService.updateTransportAttributes(
                 mTransportUid,
@@ -727,7 +727,7 @@
             throws Exception {
         setUpForUpdateTransportAttributes();
         mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
                 SecurityException.class,
@@ -766,7 +766,7 @@
     @Test
     public void testRequestBackup_whenPermissionDenied() throws Exception {
         mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
                 SecurityException.class,
@@ -780,7 +780,7 @@
     @Test
     public void testRequestBackup_whenPackagesNull() throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
                 IllegalArgumentException.class,
@@ -796,7 +796,7 @@
     @Test
     public void testRequestBackup_whenPackagesEmpty() throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
                 IllegalArgumentException.class,
@@ -811,7 +811,7 @@
     @Test
     public void testRequestBackup_whenBackupDisabled() throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
         backupManagerService.setEnabled(false);
 
         int result = backupManagerService.requestBackup(new String[] {PACKAGE_1}, mObserver, 0);
@@ -828,7 +828,7 @@
     @Test
     public void testRequestBackup_whenNotProvisioned() throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
         backupManagerService.setProvisioned(false);
 
         int result = backupManagerService.requestBackup(new String[] {PACKAGE_1}, mObserver, 0);
@@ -846,7 +846,7 @@
     public void testRequestBackup_whenTransportNotRegistered() throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         setUpCurrentTransport(mTransportManager, mTransport.unregistered());
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
         backupManagerService.setEnabled(true);
         backupManagerService.setProvisioned(true);
 
@@ -866,7 +866,7 @@
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         mShadowPackageManager.addPackage(PACKAGE_1);
         setUpCurrentTransport(mTransportManager, mTransport);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
         backupManagerService.setEnabled(true);
         backupManagerService.setProvisioned(true);
         // Haven't set PACKAGE_1 as eligible
@@ -934,7 +934,7 @@
     @Config(shadows = {ShadowBinder.class, ShadowKeyValueBackupJob.class})
     public void testBackupNow_clearsCallingIdentityForJobScheduler() {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
         setUpPowerManager(backupManagerService);
         ShadowBinder.setCallingUid(1);
 
@@ -952,7 +952,7 @@
     @Config(shadows = {ShadowBinder.class, ShadowKeyValueBackupJobException.class})
     public void testBackupNow_whenExceptionThrown_restoresCallingIdentity() {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
         setUpPowerManager(backupManagerService);
         ShadowBinder.setCallingUid(1);
 
@@ -963,54 +963,170 @@
     }
 
     private UserBackupManagerService createBackupManagerServiceForRequestBackup() {
-        UserBackupManagerService backupManagerService = createInitializedBackupManagerService();
+        UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
         backupManagerService.setEnabled(true);
         backupManagerService.setProvisioned(true);
         return backupManagerService;
     }
 
     /**
-     * Test verifying that {@link UserBackupManagerService#UserBackupManagerService(Context,
+     * Test verifying that {@link UserBackupManagerService#createAndInitializeService(Context,
      * Trampoline, HandlerThread, File, File, TransportManager)} posts a transport registration task
-     * to the backup handler thread.
+     * to the backup thread.
      */
     @Test
-    public void testConstructor_postRegisterTransports() {
+    public void testCreateAndInitializeService_postRegisterTransports() {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
 
-        createBackupManagerService();
-
-        mShadowBackupLooper.runToEndOfTasks();
-        verify(mTransportManager).registerTransports();
-    }
-
-    /**
-     * Test verifying that the {@link UserBackupManagerService#UserBackupManagerService(Context,
-     * Trampoline, HandlerThread, File, File, TransportManager)} does not directly register
-     * transports in its own thread.
-     */
-    @Test
-    public void testConstructor_doesNotRegisterTransportsSynchronously() {
-        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-
-        createBackupManagerService();
-
-        // Operations posted to mBackupThread only run with mShadowBackupLooper.runToEndOfTasks()
-        verify(mTransportManager, never()).registerTransports();
-    }
-
-    private UserBackupManagerService createBackupManagerService() {
-        return new UserBackupManagerService(
+        UserBackupManagerService.createAndInitializeService(
                 mContext,
                 new Trampoline(mContext),
                 mBackupThread,
                 mBaseStateDir,
                 mDataDir,
                 mTransportManager);
+
+        mShadowBackupLooper.runToEndOfTasks();
+        verify(mTransportManager).registerTransports();
     }
 
-    private UserBackupManagerService createInitializedBackupManagerService() {
-        return BackupManagerServiceTestUtils.createInitializedUserBackupManagerService(
+    /**
+     * Test verifying that {@link UserBackupManagerService#createAndInitializeService(Context,
+     * Trampoline, HandlerThread, File, File, TransportManager)} does not directly register
+     * transports on the main thread.
+     */
+    @Test
+    public void testCreateAndInitializeService_doesNotRegisterTransportsSynchronously() {
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+
+        UserBackupManagerService.createAndInitializeService(
+                mContext,
+                new Trampoline(mContext),
+                mBackupThread,
+                mBaseStateDir,
+                mDataDir,
+                mTransportManager);
+
+        // Operations posted to mBackupThread only run with mShadowBackupLooper.runToEndOfTasks()
+        verify(mTransportManager, never()).registerTransports();
+    }
+
+    /**
+     * Test checking non-null argument on {@link
+     * UserBackupManagerService#createAndInitializeService(Context, Trampoline, HandlerThread, File,
+     * File, TransportManager)}.
+     */
+    @Test
+    public void testCreateAndInitializeService_withNullContext_throws() {
+        expectThrows(
+                NullPointerException.class,
+                () ->
+                        UserBackupManagerService.createAndInitializeService(
+                                /* context */ null,
+                                new Trampoline(mContext),
+                                mBackupThread,
+                                mBaseStateDir,
+                                mDataDir,
+                                mTransportManager));
+    }
+
+    /**
+     * Test checking non-null argument on {@link
+     * UserBackupManagerService#createAndInitializeService(Context, Trampoline, HandlerThread, File,
+     * File, TransportManager)}.
+     */
+    @Test
+    public void testCreateAndInitializeService_withNullTrampoline_throws() {
+        expectThrows(
+                NullPointerException.class,
+                () ->
+                        UserBackupManagerService.createAndInitializeService(
+                                mContext,
+                                /* trampoline */ null,
+                                mBackupThread,
+                                mBaseStateDir,
+                                mDataDir,
+                                mTransportManager));
+    }
+
+    /**
+     * Test checking non-null argument on {@link
+     * UserBackupManagerService#createAndInitializeService(Context, Trampoline, HandlerThread, File,
+     * File, TransportManager)}.
+     */
+    @Test
+    public void testCreateAndInitializeService_withNullBackupThread_throws() {
+        expectThrows(
+                NullPointerException.class,
+                () ->
+                        UserBackupManagerService.createAndInitializeService(
+                                mContext,
+                                new Trampoline(mContext),
+                                /* backupThread */ null,
+                                mBaseStateDir,
+                                mDataDir,
+                                mTransportManager));
+    }
+
+    /**
+     * Test checking non-null argument on {@link
+     * UserBackupManagerService#createAndInitializeService(Context, Trampoline, HandlerThread, File,
+     * File, TransportManager)}.
+     */
+    @Test
+    public void testCreateAndInitializeService_withNullStateDir_throws() {
+        expectThrows(
+                NullPointerException.class,
+                () ->
+                        UserBackupManagerService.createAndInitializeService(
+                                mContext,
+                                new Trampoline(mContext),
+                                mBackupThread,
+                                /* baseStateDir */ null,
+                                mDataDir,
+                                mTransportManager));
+    }
+
+    /**
+     * Test checking non-null argument on {@link
+     * UserBackupManagerService#createAndInitializeService(Context, Trampoline, HandlerThread, File,
+     * File, TransportManager)}.
+     */
+    @Test
+    public void testCreateAndInitializeService_withNullDataDir_throws() {
+        expectThrows(
+                NullPointerException.class,
+                () ->
+                        UserBackupManagerService.createAndInitializeService(
+                                mContext,
+                                new Trampoline(mContext),
+                                mBackupThread,
+                                mBaseStateDir,
+                                /* dataDir */ null,
+                                mTransportManager));
+    }
+
+    /**
+     * Test checking non-null argument on {@link
+     * UserBackupManagerService#createAndInitializeService(Context, Trampoline, HandlerThread, File,
+     * File, TransportManager)}.
+     */
+    @Test
+    public void testCreateAndInitializeService_withNullTransportManager_throws() {
+        expectThrows(
+                NullPointerException.class,
+                () ->
+                        UserBackupManagerService.createAndInitializeService(
+                                mContext,
+                                new Trampoline(mContext),
+                                mBackupThread,
+                                mBaseStateDir,
+                                mDataDir,
+                                /* transportManager */ null));
+    }
+
+    private UserBackupManagerService createUserBackupManagerServiceAndRunTasks() {
+        return BackupManagerServiceTestUtils.createUserBackupManagerServiceAndRunTasks(
                 mContext, mBackupThread, mBaseStateDir, mDataDir, mTransportManager);
     }
 
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 1aa4999..099127c 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -25,12 +25,9 @@
 import static android.app.backup.ForwardingBackupAgent.forward;
 
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils
-        .createInitializedUserBackupManagerService;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils
-        .setUpBackupManagerServiceBasics;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils
-        .setUpBinderCallerAndApplicationAsSystem;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createUserBackupManagerServiceAndRunTasks;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBinderCallerAndApplicationAsSystem;
 import static com.android.server.backup.testing.PackageData.PM_PACKAGE;
 import static com.android.server.backup.testing.PackageData.fullBackupPackage;
 import static com.android.server.backup.testing.PackageData.keyValuePackage;
@@ -226,9 +223,8 @@
         // Needed to be able to use a real BMS instead of a mock
         setUpBinderCallerAndApplicationAsSystem(mApplication);
         mBackupManagerService =
-                spy(
-                        createInitializedUserBackupManagerService(
-                                mContext, mBaseStateDir, mDataDir, mTransportManager));
+                spy(createUserBackupManagerServiceAndRunTasks(
+                        mContext, mBaseStateDir, mDataDir, mTransportManager));
         setUpBackupManagerServiceBasics(
                 mBackupManagerService,
                 mApplication,
diff --git a/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java b/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
index bacc44e..06f6d21 100644
--- a/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
+++ b/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
@@ -52,23 +52,36 @@
 /** Test utils for {@link UserBackupManagerService} and friends. */
 public class BackupManagerServiceTestUtils {
     /**
-     * If the class-under-test is going to execute methods as the system, it's a good idea to also
-     * call {@link #setUpBinderCallerAndApplicationAsSystem(Application)} before this method.
+     * Creates an instance of {@link UserBackupManagerService} with a new backup thread and runs
+     * tasks that were posted to it during instantiation.
+     *
+     * <p>If the class-under-test is going to execute methods as the system, it's a good idea to
+     * also call {@link #setUpBinderCallerAndApplicationAsSystem(Application)} before this method.
+     *
+     * @see #createUserBackupManagerServiceAndRunTasks(Context, HandlerThread, File, File,
+     *     TransportManager)
      */
-    public static UserBackupManagerService createInitializedUserBackupManagerService(
+    public static UserBackupManagerService createUserBackupManagerServiceAndRunTasks(
             Context context, File baseStateDir, File dataDir, TransportManager transportManager) {
-        return createInitializedUserBackupManagerService(
+        return createUserBackupManagerServiceAndRunTasks(
                 context, startBackupThread(null), baseStateDir, dataDir, transportManager);
     }
 
-    public static UserBackupManagerService createInitializedUserBackupManagerService(
+    /**
+     * Creates an instance of {@link UserBackupManagerService} with the supplied backup thread
+     * {@code backupThread} and runs tasks that were posted to it during instantiation.
+     *
+     * <p>If the class-under-test is going to execute methods as the system, it's a good idea to
+     * also call {@link #setUpBinderCallerAndApplicationAsSystem(Application)} before this method.
+     */
+    public static UserBackupManagerService createUserBackupManagerServiceAndRunTasks(
             Context context,
             HandlerThread backupThread,
             File baseStateDir,
             File dataDir,
             TransportManager transportManager) {
         UserBackupManagerService backupManagerService =
-                new UserBackupManagerService(
+                UserBackupManagerService.createAndInitializeService(
                         context,
                         new Trampoline(context),
                         backupThread,
diff --git a/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java b/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java
index beb5941..30c7336 100644
--- a/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java
+++ b/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java
@@ -7,7 +7,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.os.Looper;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 
@@ -44,7 +43,7 @@
         when(mMockNative.pauseGeofence(anyInt())).thenReturn(true);
         when(mMockNative.removeGeofence(anyInt())).thenReturn(true);
         when(mMockNative.resumeGeofence(anyInt(), anyInt())).thenReturn(true);
-        mTestProvider = new GnssGeofenceProvider(Looper.myLooper(), mMockNative);
+        mTestProvider = new GnssGeofenceProvider(mMockNative);
         mTestProvider.addCircularHardwareGeofence(GEOFENCE_ID, LATITUDE,
                 LONGITUDE, RADIUS, LAST_TRANSITION, MONITOR_TRANSITIONS,
                 NOTIFICATION_RESPONSIVENESS,
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index e804342..d49e78a 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -69,10 +69,10 @@
         "liblog",
         "liblzma",
         "libnativehelper",
-        "libnetdaidl",
         "libui",
         "libunwind",
         "libutils",
+        "netd_aidl_interface-cpp",
     ],
 
     dxflags: ["--multi-dex"],
diff --git a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
index 7c00299..fd010f1 100644
--- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
@@ -23,6 +23,7 @@
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
 
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -43,10 +44,14 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.test.mock.MockContentResolver;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.util.test.FakeSettingsProvider;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -97,6 +102,7 @@
     private FileDescriptor mFileDescriptorStub = new FileDescriptor();
 
     private TrampolineTestable mTrampoline;
+    private MockContentResolver mContentResolver;
 
     @Before
     public void setUp() {
@@ -110,6 +116,10 @@
         when(mSuppressFileMock.getParentFile()).thenReturn(mSuppressFileParentMock);
 
         mTrampoline = new TrampolineTestable(mContextMock);
+
+        mContentResolver = new MockContentResolver();
+        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+        when(mContextMock.getContentResolver()).thenReturn(mContentResolver);
     }
 
     @Test
@@ -118,6 +128,24 @@
     }
 
     @Test
+    public void startServiceForUser_whenMultiUserSettingDisabled_isIgnored() {
+        Settings.Global.putInt(mContentResolver, Settings.Global.BACKUP_MULTI_USER_ENABLED, 0);
+
+        mTrampoline.startServiceForUser(10);
+
+        verify(mBackupManagerServiceMock, never()).startServiceForUser(10);
+    }
+
+    @Test
+    public void startServiceForUser_whenMultiUserSettingEnabled_callsBackupManagerService() {
+        Settings.Global.putInt(mContentResolver, Settings.Global.BACKUP_MULTI_USER_ENABLED, 1);
+
+        mTrampoline.startServiceForUser(10);
+
+        verify(mBackupManagerServiceMock).startServiceForUser(10);
+    }
+
+    @Test
     public void initializeService_forUserSystem_successfullyInitialized() {
         mTrampoline.initializeService(UserHandle.USER_SYSTEM);
 
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 5dc6d83..c3a0dda 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -4163,7 +4163,7 @@
         // test reset password with token
         when(getServices().lockPatternUtils.setLockCredentialWithToken(eq(password),
                 eq(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD),
-                eq(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED), eq(handle), eq(token),
+                eq(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC), eq(handle), eq(token),
                 eq(UserHandle.USER_SYSTEM)))
                 .thenReturn(true);
         assertTrue(dpm.resetPasswordWithToken(admin1, password, token, 0));
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 7bcb571..c639c28 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -16,13 +16,13 @@
 
 package com.android.server.pm;
 
+import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
-import android.app.ActivityManager;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -162,6 +162,29 @@
     }
 
     @MediumTest
+    public void testRemoveUserByHandle() {
+        UserInfo userInfo = createUser("Guest 1", UserInfo.FLAG_GUEST);
+        final UserHandle user = userInfo.getUserHandle();
+        synchronized (mUserRemoveLock) {
+            mUserManager.removeUser(user);
+            long time = System.currentTimeMillis();
+            while (mUserManager.getUserInfo(user.getIdentifier()) != null) {
+                try {
+                    mUserRemoveLock.wait(REMOVE_CHECK_INTERVAL_MILLIS);
+                } catch (InterruptedException ie) {
+                    Thread.currentThread().interrupt();
+                    return;
+                }
+                if (System.currentTimeMillis() - time > REMOVE_TIMEOUT_MILLIS) {
+                    fail("Timeout waiting for removeUser. userId = " + user.getIdentifier());
+                }
+            }
+        }
+
+        assertFalse(findUser(userInfo.id));
+    }
+
+    @MediumTest
     public void testAddGuest() throws Exception {
         UserInfo userInfo1 = createUser("Guest 1", UserInfo.FLAG_GUEST);
         UserInfo userInfo2 = createUser("Guest 2", UserInfo.FLAG_GUEST);
diff --git a/services/tests/servicestests/src/com/android/server/signedconfig/SignedConfigTest.java b/services/tests/servicestests/src/com/android/server/signedconfig/SignedConfigTest.java
new file mode 100644
index 0000000..a9d4519
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/signedconfig/SignedConfigTest.java
@@ -0,0 +1,328 @@
+/*
+ * 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.server.signedconfig;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+
+import static java.util.Collections.emptySet;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.collect.Sets;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+
+
+/**
+ * Tests for {@link SignedConfig}
+ */
+@RunWith(AndroidJUnit4.class)
+public class SignedConfigTest {
+
+    private static Set<String> setOf(String... values) {
+        return Sets.newHashSet(values);
+    }
+
+    @Test
+    public void testParsePerSdkConfigSdkMinMax() throws JSONException, InvalidConfigException {
+        JSONObject json = new JSONObject("{\"minSdk\":2, \"maxSdk\": 3, \"values\": []}");
+        SignedConfig.PerSdkConfig config = SignedConfig.parsePerSdkConfig(json, emptySet());
+        assertThat(config.minSdk).isEqualTo(2);
+        assertThat(config.maxSdk).isEqualTo(3);
+    }
+
+    @Test
+    public void testParsePerSdkConfigNoMinSdk() throws JSONException {
+        JSONObject json = new JSONObject("{\"maxSdk\": 3, \"values\": []}");
+        try {
+            SignedConfig.parsePerSdkConfig(json, emptySet());
+            fail("Expected InvalidConfigException or JSONException");
+        } catch (JSONException | InvalidConfigException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testParsePerSdkConfigNoMaxSdk() throws JSONException {
+        JSONObject json = new JSONObject("{\"minSdk\": 1, \"values\": []}");
+        try {
+            SignedConfig.parsePerSdkConfig(json, emptySet());
+            fail("Expected InvalidConfigException or JSONException");
+        } catch (JSONException | InvalidConfigException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testParsePerSdkConfigNoValues() throws JSONException {
+        JSONObject json = new JSONObject("{\"minSdk\": 1, \"maxSdk\": 3}");
+        try {
+            SignedConfig.parsePerSdkConfig(json, emptySet());
+            fail("Expected InvalidConfigException or JSONException");
+        } catch (JSONException | InvalidConfigException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testParsePerSdkConfigSdkNullMinSdk() throws JSONException, InvalidConfigException {
+        JSONObject json = new JSONObject("{\"minSdk\":null, \"maxSdk\": 3, \"values\": []}");
+        try {
+            SignedConfig.parsePerSdkConfig(json, emptySet());
+            fail("Expected InvalidConfigException or JSONException");
+        } catch (JSONException | InvalidConfigException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testParsePerSdkConfigSdkNullMaxSdk() throws JSONException, InvalidConfigException {
+        JSONObject json = new JSONObject("{\"minSdk\":1, \"maxSdk\": null, \"values\": []}");
+        try {
+            SignedConfig.parsePerSdkConfig(json, emptySet());
+            fail("Expected InvalidConfigException or JSONException");
+        } catch (JSONException | InvalidConfigException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testParsePerSdkConfigNullValues() throws JSONException {
+        JSONObject json = new JSONObject("{\"minSdk\": 1, \"maxSdk\": 3, \"values\": null}");
+        try {
+            SignedConfig.parsePerSdkConfig(json, emptySet());
+            fail("Expected InvalidConfigException or JSONException");
+        } catch (JSONException | InvalidConfigException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testParsePerSdkConfigZeroValues()
+            throws JSONException, InvalidConfigException {
+        JSONObject json = new JSONObject("{\"minSdk\": 1, \"maxSdk\": 3, \"values\": []}");
+        SignedConfig.PerSdkConfig config = SignedConfig.parsePerSdkConfig(json, setOf("a", "b"));
+        assertThat(config.values).hasSize(0);
+    }
+
+    @Test
+    public void testParsePerSdkConfigSingleKey()
+            throws JSONException, InvalidConfigException {
+        JSONObject json = new JSONObject(
+                "{\"minSdk\": 1, \"maxSdk\": 1, \"values\": [{\"key\":\"a\", \"value\": \"1\"}]}");
+        SignedConfig.PerSdkConfig config = SignedConfig.parsePerSdkConfig(json, setOf("a", "b"));
+        assertThat(config.values).containsExactly("a", "1");
+    }
+
+    @Test
+    public void testParsePerSdkConfigMultiKeys()
+            throws JSONException, InvalidConfigException {
+        JSONObject json = new JSONObject(
+                "{\"minSdk\": 1, \"maxSdk\": 1, \"values\": [{\"key\":\"a\", \"value\": \"1\"}, "
+                        + "{\"key\":\"c\", \"value\": \"2\"}]}");
+        SignedConfig.PerSdkConfig config = SignedConfig.parsePerSdkConfig(
+                json, setOf("a", "b", "c"));
+        assertThat(config.values).containsExactly("a", "1", "c", "2");
+    }
+
+    @Test
+    public void testParsePerSdkConfigSingleKeyNotAllowed() throws JSONException {
+        JSONObject json = new JSONObject(
+                "{\"minSdk\": 1, \"maxSdk\": 1, \"values\": [{\"key\":\"a\", \"value\": \"1\"}]}");
+        try {
+            SignedConfig.parsePerSdkConfig(json, setOf("b"));
+            fail("Expected InvalidConfigException or JSONException");
+        } catch (JSONException | InvalidConfigException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testParsePerSdkConfigSingleKeyNoValue()
+            throws JSONException, InvalidConfigException {
+        JSONObject json = new JSONObject(
+                "{\"minSdk\": 1, \"maxSdk\": 1, \"values\": [{\"key\":\"a\"}]}");
+        SignedConfig.PerSdkConfig config = SignedConfig.parsePerSdkConfig(json, setOf("a", "b"));
+        assertThat(config.values).containsExactly("a", null);
+    }
+
+    @Test
+    public void testParsePerSdkConfigValuesInvalid() throws JSONException  {
+        JSONObject json = new JSONObject("{\"minSdk\": 1, \"maxSdk\": 1,  \"values\": \"foo\"}");
+        try {
+            SignedConfig.parsePerSdkConfig(json, emptySet());
+            fail("Expected InvalidConfigException or JSONException");
+        } catch (JSONException | InvalidConfigException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testParsePerSdkConfigConfigEntryInvalid() throws JSONException {
+        JSONObject json = new JSONObject("{\"minSdk\": 1, \"maxSdk\": 1,  \"values\": [1, 2]}");
+        try {
+            SignedConfig.parsePerSdkConfig(json, emptySet());
+            fail("Expected InvalidConfigException or JSONException");
+        } catch (JSONException | InvalidConfigException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testParsePerSdkConfigConfigEntryNull() throws JSONException {
+        JSONObject json = new JSONObject("{\"minSdk\": 1, \"maxSdk\": 1,  \"values\": [null]}");
+        try {
+            SignedConfig.parsePerSdkConfig(json, emptySet());
+            fail("Expected InvalidConfigException or JSONException");
+        } catch (JSONException | InvalidConfigException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testParseVersion() throws InvalidConfigException {
+        SignedConfig config = SignedConfig.parse(
+                "{\"version\": 1, \"config\": []}", emptySet());
+        assertThat(config.version).isEqualTo(1);
+    }
+
+    @Test
+    public void testParseVersionInvalid() {
+        try {
+            SignedConfig.parse("{\"version\": \"notanint\", \"config\": []}", emptySet());
+            fail("Expected InvalidConfigException");
+        } catch (InvalidConfigException e) {
+            //expected
+        }
+    }
+
+    @Test
+    public void testParseNoVersion() {
+        try {
+            SignedConfig.parse("{\"config\": []}", emptySet());
+            fail("Expected InvalidConfigException");
+        } catch (InvalidConfigException e) {
+            //expected
+        }
+    }
+
+    @Test
+    public void testParseNoConfig() {
+        try {
+            SignedConfig.parse("{\"version\": 1}", emptySet());
+            fail("Expected InvalidConfigException");
+        } catch (InvalidConfigException e) {
+            //expected
+        }
+    }
+
+    @Test
+    public void testParseConfigNull() {
+        try {
+            SignedConfig.parse("{\"version\": 1, \"config\": null}", emptySet());
+            fail("Expected InvalidConfigException");
+        } catch (InvalidConfigException e) {
+            //expected
+        }
+    }
+
+    @Test
+    public void testParseVersionNull() {
+        try {
+            SignedConfig.parse("{\"version\": null, \"config\": []}", emptySet());
+            fail("Expected InvalidConfigException");
+        } catch (InvalidConfigException e) {
+            //expected
+        }
+    }
+
+    @Test
+    public void testParseConfigInvalidEntry() {
+        try {
+            SignedConfig.parse("{\"version\": 1, \"config\": [{}]}", emptySet());
+            fail("Expected InvalidConfigException");
+        } catch (InvalidConfigException e) {
+            //expected
+        }
+    }
+
+    @Test
+    public void testParseSdkConfigSingle() throws InvalidConfigException {
+        SignedConfig config = SignedConfig.parse(
+                "{\"version\": 1, \"config\":[{\"minSdk\": 1, \"maxSdk\": 1, \"values\": []}]}",
+                emptySet());
+        assertThat(config.perSdkConfig).hasSize(1);
+    }
+
+    @Test
+    public void testParseSdkConfigMultiple() throws InvalidConfigException {
+        SignedConfig config = SignedConfig.parse(
+                "{\"version\": 1, \"config\":[{\"minSdk\": 1, \"maxSdk\": 1, \"values\": []}, "
+                        + "{\"minSdk\": 2, \"maxSdk\": 2, \"values\": []}]}", emptySet());
+        assertThat(config.perSdkConfig).hasSize(2);
+    }
+
+    @Test
+    public void testGetMatchingConfigFirst() {
+        SignedConfig.PerSdkConfig sdk1 = new SignedConfig.PerSdkConfig(
+                1, 1, Collections.emptyMap());
+        SignedConfig.PerSdkConfig sdk2 = new SignedConfig.PerSdkConfig(
+                2, 2, Collections.emptyMap());
+        SignedConfig config = new SignedConfig(0, Arrays.asList(sdk1, sdk2));
+        assertThat(config.getMatchingConfig(1)).isEqualTo(sdk1);
+    }
+
+    @Test
+    public void testGetMatchingConfigSecond() {
+        SignedConfig.PerSdkConfig sdk1 = new SignedConfig.PerSdkConfig(
+                1, 1, Collections.emptyMap());
+        SignedConfig.PerSdkConfig sdk2 = new SignedConfig.PerSdkConfig(
+                2, 2, Collections.emptyMap());
+        SignedConfig config = new SignedConfig(0, Arrays.asList(sdk1, sdk2));
+        assertThat(config.getMatchingConfig(2)).isEqualTo(sdk2);
+    }
+
+    @Test
+    public void testGetMatchingConfigInRange() {
+        SignedConfig.PerSdkConfig sdk13 = new SignedConfig.PerSdkConfig(
+                1, 3, Collections.emptyMap());
+        SignedConfig.PerSdkConfig sdk46 = new SignedConfig.PerSdkConfig(
+                4, 6, Collections.emptyMap());
+        SignedConfig config = new SignedConfig(0, Arrays.asList(sdk13, sdk46));
+        assertThat(config.getMatchingConfig(2)).isEqualTo(sdk13);
+    }
+
+    @Test
+    public void testGetMatchingConfigNoMatch() {
+        SignedConfig.PerSdkConfig sdk1 = new SignedConfig.PerSdkConfig(
+                1, 1, Collections.emptyMap());
+        SignedConfig.PerSdkConfig sdk2 = new SignedConfig.PerSdkConfig(
+                2, 2, Collections.emptyMap());
+        SignedConfig config = new SignedConfig(0, Arrays.asList(sdk1, sdk2));
+        assertThat(config.getMatchingConfig(3)).isNull();
+    }
+
+}
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index ca8cc0d..7a5eaa8 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -50,9 +50,9 @@
         "liblog",
         "liblzma",
         "libnativehelper",
-        "libnetdaidl",
         "libui",
         "libunwindstack",
         "libutils",
+        "netd_aidl_interface-cpp",
     ],
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
index 82e0fbe..a71aca5 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
@@ -106,8 +106,8 @@
         mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken);
         TestableLooper.get(this).processAllMessages();
 
-        verify(mIContentProvider).call(anyString(), eq(SliceProvider.METHOD_PIN), eq(null),
-                argThat(b -> {
+        verify(mIContentProvider).call(anyString(), anyString(), eq(SliceProvider.METHOD_PIN),
+                eq(null), argThat(b -> {
                     assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI));
                     return true;
                 }));
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 048384e..f6871b3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -162,7 +162,8 @@
         assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
 
         // Ensure that the override mode is restored to undefined
-        assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+        assertEquals(WINDOWING_MODE_UNDEFINED,
+                primarySplitScreen.getRequestedOverrideWindowingMode());
     }
 
     @Test
@@ -184,7 +185,8 @@
         assertEquals(0, mDefaultDisplay.getIndexOf(primarySplitScreen));
 
         // Ensure that the override mode is restored to what it was (fullscreen)
-        assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getOverrideWindowingMode());
+        assertEquals(WINDOWING_MODE_FULLSCREEN,
+                primarySplitScreen.getRequestedOverrideWindowingMode());
     }
 
     @Test
@@ -193,11 +195,13 @@
                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
-        assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+        assertEquals(WINDOWING_MODE_UNDEFINED,
+                primarySplitScreen.getRequestedOverrideWindowingMode());
 
         mDefaultDisplay.setWindowingMode(WINDOWING_MODE_FREEFORM);
         assertEquals(WINDOWING_MODE_FREEFORM, primarySplitScreen.getWindowingMode());
-        assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+        assertEquals(WINDOWING_MODE_UNDEFINED,
+                primarySplitScreen.getRequestedOverrideWindowingMode());
     }
 
     @Test
@@ -206,11 +210,13 @@
                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
-        assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+        assertEquals(WINDOWING_MODE_UNDEFINED,
+                primarySplitScreen.getRequestedOverrideWindowingMode());
 
         primarySplitScreen.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         // setting windowing mode should still work even though resolved mode is already fullscreen
-        assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getOverrideWindowingMode());
+        assertEquals(WINDOWING_MODE_FULLSCREEN,
+                primarySplitScreen.getRequestedOverrideWindowingMode());
 
         mDefaultDisplay.setWindowingMode(WINDOWING_MODE_FREEFORM);
         assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 5c918b4..7c43cf3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -135,8 +135,8 @@
         final Rect bounds = new Rect(10, 10, 100, 100);
 
         mStarter.updateBounds(task, bounds);
-        assertEquals(bounds, task.getOverrideBounds());
-        assertEquals(new Rect(), task.getStack().getOverrideBounds());
+        assertEquals(bounds, task.getRequestedOverrideBounds());
+        assertEquals(new Rect(), task.getStack().getRequestedOverrideBounds());
 
         // When in a resizeable stack, the stack bounds should be updated as well.
         final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor)
@@ -151,10 +151,10 @@
 
         // In the case of no animation, the stack and task bounds should be set immediately.
         if (!ANIMATE) {
-            assertEquals(bounds, task2.getStack().getOverrideBounds());
-            assertEquals(bounds, task2.getOverrideBounds());
+            assertEquals(bounds, task2.getStack().getRequestedOverrideBounds());
+            assertEquals(bounds, task2.getRequestedOverrideBounds());
         } else {
-            assertEquals(new Rect(), task2.getOverrideBounds());
+            assertEquals(new Rect(), task2.getRequestedOverrideBounds());
         }
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 3a56419..f553c35 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -408,6 +408,7 @@
             initialize(intentFirewall, intentController, looper);
             initRootActivityContainerMocks(wm);
             setWindowManager(wm);
+            createDefaultDisplay();
         }
 
         void initRootActivityContainerMocks(WindowManagerService wm) {
@@ -424,7 +425,9 @@
             // Called when moving activity to pinned stack.
             doNothing().when(mRootActivityContainer).ensureActivitiesVisible(any(), anyInt(),
                     anyBoolean());
+        }
 
+        void createDefaultDisplay() {
             // Create a default display and put a home stack on it so that we'll always have
             // something focusable.
             mDefaultDisplay = TestActivityDisplay.create(mStackSupervisor, DEFAULT_DISPLAY);
@@ -598,10 +601,8 @@
         }
 
         @Override
-        protected DisplayWindowController createWindowContainerController() {
-            DisplayWindowController out = mock(DisplayWindowController.class);
-            out.mContainer = WindowTestUtils.createTestDisplayContent();
-            return out;
+        protected DisplayContent createDisplayContent() {
+            return WindowTestUtils.createTestDisplayContent();
         }
 
         void removeAllTasks() {
@@ -616,6 +617,7 @@
 
     private static WindowManagerService prepareMockWindowManager() {
         final WindowManagerService service = mock(WindowManagerService.class);
+        service.mRoot = mock(RootWindowContainer.class);
 
         doAnswer((InvocationOnMock invocationOnMock) -> {
             final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 577859c..fa42289 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -80,7 +80,7 @@
     @Test
     public void testForceOverride() {
         mWm.prepareAppTransition(TRANSIT_KEYGUARD_UNOCCLUDE, false /* alwaysKeepCurrent */);
-        mDc.getController().prepareAppTransition(TRANSIT_ACTIVITY_OPEN,
+        mDc.prepareAppTransition(TRANSIT_ACTIVITY_OPEN,
                 false /* alwaysKeepCurrent */, 0 /* flags */, true /* forceOverride */);
         assertEquals(TRANSIT_ACTIVITY_OPEN, mDc.mAppTransition.getAppTransition());
     }
@@ -102,8 +102,8 @@
     @Test
     public void testAppTransitionStateForMultiDisplay() {
         // Create 2 displays & presume both display the state is ON for ready to display & animate.
-        final DisplayContent dc1 = createNewDisplayWithController(Display.STATE_ON);
-        final DisplayContent dc2 = createNewDisplayWithController(Display.STATE_ON);
+        final DisplayContent dc1 = createNewDisplay(Display.STATE_ON);
+        final DisplayContent dc2 = createNewDisplay(Display.STATE_ON);
 
         // Create 2 app window tokens to represent 2 activity window.
         final WindowTestUtils.TestAppWindowToken token1 = createTestAppWindowToken(dc1,
@@ -117,10 +117,10 @@
 
         // Simulate activity resume / finish flows to prepare app transition & set visibility,
         // make sure transition is set as expected for each display.
-        dc1.getController().prepareAppTransition(TRANSIT_ACTIVITY_OPEN,
+        dc1.prepareAppTransition(TRANSIT_ACTIVITY_OPEN,
                 false /* alwaysKeepCurrent */, 0 /* flags */, false /* forceOverride */);
         assertEquals(TRANSIT_ACTIVITY_OPEN, dc1.mAppTransition.getAppTransition());
-        dc2.getController().prepareAppTransition(TRANSIT_ACTIVITY_CLOSE,
+        dc2.prepareAppTransition(TRANSIT_ACTIVITY_CLOSE,
                 false /* alwaysKeepCurrent */, 0 /* flags */, false /* forceOverride */);
         assertEquals(TRANSIT_ACTIVITY_CLOSE, dc2.mAppTransition.getAppTransition());
         // One activity window is visible for resuming & the other activity window is invisible
@@ -138,8 +138,8 @@
     @Test
     public void testCleanAppTransitionWhenTaskStackReparent() {
         // Create 2 displays & presume both display the state is ON for ready to display & animate.
-        final DisplayContent dc1 = createNewDisplayWithController(Display.STATE_ON);
-        final DisplayContent dc2 = createNewDisplayWithController(Display.STATE_ON);
+        final DisplayContent dc1 = createNewDisplay(Display.STATE_ON);
+        final DisplayContent dc2 = createNewDisplay(Display.STATE_ON);
 
         final TaskStack stack1 = createTaskStackOnDisplay(dc1);
         final Task task1 = createTaskInStack(stack1, 0 /* userId */);
@@ -151,7 +151,7 @@
         dc1.mClosingApps.add(token1);
         assertTrue(dc1.mClosingApps.size() > 0);
 
-        dc1.getController().prepareAppTransition(TRANSIT_ACTIVITY_OPEN,
+        dc1.prepareAppTransition(TRANSIT_ACTIVITY_OPEN,
                 false /* alwaysKeepCurrent */, 0 /* flags */, false /* forceOverride */);
         assertEquals(TRANSIT_ACTIVITY_OPEN, dc1.mAppTransition.getAppTransition());
         assertTrue(dc1.mAppTransition.isTransitionSet());
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 0ee532d..92b4dbb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -155,15 +155,15 @@
 
         // Set initial orientation and update.
         mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
-        mWm.updateOrientationFromAppTokens(mDisplayContent.getOverrideConfiguration(), null,
-                mDisplayContent.getDisplayId());
+        mWm.updateOrientationFromAppTokens(mDisplayContent.getRequestedOverrideConfiguration(),
+                null, mDisplayContent.getDisplayId());
         assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mDisplayContent.getLastOrientation());
         appWindow.mResizeReported = false;
 
         // Update the orientation to perform 180 degree rotation and check that resize was reported.
         mToken.setOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
-        mWm.updateOrientationFromAppTokens(mDisplayContent.getOverrideConfiguration(), null,
-                mDisplayContent.getDisplayId());
+        mWm.updateOrientationFromAppTokens(mDisplayContent.getRequestedOverrideConfiguration(),
+                null, mDisplayContent.getDisplayId());
         mWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
         assertEquals(SCREEN_ORIENTATION_REVERSE_LANDSCAPE, mDisplayContent.getLastOrientation());
         assertTrue(appWindow.mResizeReported);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java
index 82a200b..e7f7d21 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java
@@ -27,6 +27,7 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
 import static android.content.res.Configuration.EMPTY;
+import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -55,22 +56,22 @@
     public void testConfigurationInit() {
         // Check root container initial config.
         final TestConfigurationContainer root = new TestConfigurationContainer();
-        assertEquals(EMPTY, root.getOverrideConfiguration());
+        assertEquals(EMPTY, root.getRequestedOverrideConfiguration());
         assertEquals(EMPTY, root.getMergedOverrideConfiguration());
         assertEquals(EMPTY, root.getConfiguration());
 
         // Check child initial config.
         final TestConfigurationContainer child1 = root.addChild();
-        assertEquals(EMPTY, child1.getOverrideConfiguration());
+        assertEquals(EMPTY, child1.getRequestedOverrideConfiguration());
         assertEquals(EMPTY, child1.getMergedOverrideConfiguration());
         assertEquals(EMPTY, child1.getConfiguration());
 
         // Check child initial config if root has overrides.
         final Configuration rootOverrideConfig = new Configuration();
         rootOverrideConfig.fontScale = 1.3f;
-        root.onOverrideConfigurationChanged(rootOverrideConfig);
+        root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
         final TestConfigurationContainer child2 = root.addChild();
-        assertEquals(EMPTY, child2.getOverrideConfiguration());
+        assertEquals(EMPTY, child2.getRequestedOverrideConfiguration());
         assertEquals(rootOverrideConfig, child2.getMergedOverrideConfiguration());
         assertEquals(rootOverrideConfig, child2.getConfiguration());
 
@@ -83,7 +84,7 @@
         rootFullConfig.updateFrom(rootOverrideConfig);
 
         final TestConfigurationContainer child3 = root.addChild();
-        assertEquals(EMPTY, child3.getOverrideConfiguration());
+        assertEquals(EMPTY, child3.getRequestedOverrideConfiguration());
         assertEquals(rootOverrideConfig, child3.getMergedOverrideConfiguration());
         assertEquals(rootFullConfig, child3.getConfiguration());
     }
@@ -94,24 +95,24 @@
         final TestConfigurationContainer root = new TestConfigurationContainer();
         final Configuration rootOverrideConfig = new Configuration();
         rootOverrideConfig.fontScale = 1.3f;
-        root.onOverrideConfigurationChanged(rootOverrideConfig);
+        root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
 
         // Init child's config.
         final TestConfigurationContainer child = root.addChild();
         final Configuration childOverrideConfig = new Configuration();
         childOverrideConfig.densityDpi = 320;
-        child.onOverrideConfigurationChanged(childOverrideConfig);
+        child.onRequestedOverrideConfigurationChanged(childOverrideConfig);
         final Configuration mergedOverrideConfig = new Configuration(root.getConfiguration());
         mergedOverrideConfig.updateFrom(childOverrideConfig);
 
         // Check configuration update when child is removed from parent.
         root.removeChild(child);
-        assertEquals(childOverrideConfig, child.getOverrideConfiguration());
+        assertEquals(childOverrideConfig, child.getRequestedOverrideConfiguration());
         assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration());
         assertEquals(mergedOverrideConfig, child.getConfiguration());
 
         // It may be paranoia... but let's check if parent's config didn't change after removal.
-        assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+        assertEquals(rootOverrideConfig, root.getRequestedOverrideConfiguration());
         assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
         assertEquals(rootOverrideConfig, root.getConfiguration());
 
@@ -119,13 +120,13 @@
         final TestConfigurationContainer root2 = new TestConfigurationContainer();
         final Configuration rootOverrideConfig2 = new Configuration();
         rootOverrideConfig2.fontScale = 1.1f;
-        root2.onOverrideConfigurationChanged(rootOverrideConfig2);
+        root2.onRequestedOverrideConfigurationChanged(rootOverrideConfig2);
 
         // Check configuration update when child is added to different parent.
         mergedOverrideConfig.setTo(rootOverrideConfig2);
         mergedOverrideConfig.updateFrom(childOverrideConfig);
         root2.addChild(child);
-        assertEquals(childOverrideConfig, child.getOverrideConfiguration());
+        assertEquals(childOverrideConfig, child.getRequestedOverrideConfiguration());
         assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration());
         assertEquals(mergedOverrideConfig, child.getConfiguration());
     }
@@ -141,24 +142,24 @@
         final Configuration rootOverrideConfig = new Configuration();
         rootOverrideConfig.fontScale = 1.3f;
         rootOverrideConfig.orientation = SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
-        root.onOverrideConfigurationChanged(rootOverrideConfig);
+        root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
 
         // Init children.
         final TestConfigurationContainer child1 = root.addChild();
         final Configuration childOverrideConfig1 = new Configuration();
         childOverrideConfig1.densityDpi = 320;
         childOverrideConfig1.orientation = SCREEN_ORIENTATION_LANDSCAPE;
-        child1.onOverrideConfigurationChanged(childOverrideConfig1);
+        child1.onRequestedOverrideConfigurationChanged(childOverrideConfig1);
 
         final TestConfigurationContainer child2 = child1.addChild();
         final Configuration childOverrideConfig2 = new Configuration();
         childOverrideConfig2.screenWidthDp = 150;
         childOverrideConfig2.orientation = SCREEN_ORIENTATION_PORTRAIT;
-        child2.onOverrideConfigurationChanged(childOverrideConfig2);
+        child2.onRequestedOverrideConfigurationChanged(childOverrideConfig2);
 
         // Check configuration on all levels when root override is updated.
         rootOverrideConfig.smallestScreenWidthDp = 200;
-        root.onOverrideConfigurationChanged(rootOverrideConfig);
+        root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
 
         final Configuration mergedOverrideConfig1 = new Configuration(rootOverrideConfig);
         mergedOverrideConfig1.updateFrom(childOverrideConfig1);
@@ -168,15 +169,15 @@
         mergedOverrideConfig2.updateFrom(childOverrideConfig2);
         final Configuration mergedConfig2 = new Configuration(mergedOverrideConfig2);
 
-        assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+        assertEquals(rootOverrideConfig, root.getRequestedOverrideConfiguration());
         assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
         assertEquals(rootOverrideConfig, root.getConfiguration());
 
-        assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
+        assertEquals(childOverrideConfig1, child1.getRequestedOverrideConfiguration());
         assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
         assertEquals(mergedConfig1, child1.getConfiguration());
 
-        assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
+        assertEquals(childOverrideConfig2, child2.getRequestedOverrideConfiguration());
         assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
         assertEquals(mergedConfig2, child2.getConfiguration());
 
@@ -194,15 +195,15 @@
         mergedConfig2.setTo(mergedConfig1);
         mergedConfig2.updateFrom(mergedOverrideConfig2);
 
-        assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+        assertEquals(rootOverrideConfig, root.getRequestedOverrideConfiguration());
         assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
         assertEquals(mergedRootConfig, root.getConfiguration());
 
-        assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
+        assertEquals(childOverrideConfig1, child1.getRequestedOverrideConfiguration());
         assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
         assertEquals(mergedConfig1, child1.getConfiguration());
 
-        assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
+        assertEquals(childOverrideConfig2, child2.getRequestedOverrideConfiguration());
         assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
         assertEquals(mergedConfig2, child2.getConfiguration());
     }
@@ -274,15 +275,55 @@
         final Configuration config = new Configuration();
         config.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
         config.windowConfiguration.setAppBounds(10, 10, 10, 10);
-        container.onOverrideConfigurationChanged(config);
+        container.onRequestedOverrideConfigurationChanged(config);
         container.registerConfigurationChangeListener(listener);
         // Assert listener got the current config. of the container after it was registered.
         assertEquals(config, listener.mOverrideConfiguration);
         // Assert listener gets changes to override configuration.
-        container.onOverrideConfigurationChanged(EMPTY);
+        container.onRequestedOverrideConfigurationChanged(EMPTY);
         assertEquals(EMPTY, listener.mOverrideConfiguration);
     }
 
+    @Test
+    public void testConfigurationConstraints() {
+        // Init root config.
+        final TestConfigurationContainer root = new TestConfigurationContainer();
+        final Configuration rootOverrideConfig = new Configuration();
+        rootOverrideConfig.smallestScreenWidthDp = 140;
+        root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
+
+        // Init child with constraint
+        final TestConfigurationChangeListener listener = new TestConfigurationChangeListener();
+        final TestConfigurationContainer child1 = root.addConstraintChild();
+        child1.registerConfigurationChangeListener(listener);
+        final Configuration childOverrideConfig1 = new Configuration();
+        childOverrideConfig1.orientation = SCREEN_ORIENTATION_LANDSCAPE;
+        child1.onRequestedOverrideConfigurationChanged(childOverrideConfig1);
+
+        assertEquals(SMALLEST_SCREEN_WIDTH_DP_UNDEFINED,
+                child1.getRequestedOverrideConfiguration().smallestScreenWidthDp);
+        assertEquals(100, child1.getConfiguration().smallestScreenWidthDp);
+        assertEquals(100, listener.mOverrideConfiguration.smallestScreenWidthDp);
+
+        // Check configuration on all levels when root override is updated.
+        rootOverrideConfig.smallestScreenWidthDp = 80;
+        root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
+
+        assertEquals(SMALLEST_SCREEN_WIDTH_DP_UNDEFINED,
+                child1.getRequestedOverrideConfiguration().smallestScreenWidthDp);
+        assertEquals(80, child1.getConfiguration().smallestScreenWidthDp);
+        assertEquals(80, listener.mOverrideConfiguration.smallestScreenWidthDp);
+
+        rootOverrideConfig.smallestScreenWidthDp = 180;
+        root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
+
+        assertEquals(SMALLEST_SCREEN_WIDTH_DP_UNDEFINED,
+                child1.getRequestedOverrideConfiguration().smallestScreenWidthDp);
+        assertEquals(100, child1.getConfiguration().smallestScreenWidthDp);
+        assertEquals(100, child1.getMergedOverrideConfiguration().smallestScreenWidthDp);
+        assertEquals(100, listener.mOverrideConfiguration.smallestScreenWidthDp);
+    }
+
     /**
      * Contains minimal implementation of {@link ConfigurationContainer}'s abstract behavior needed
      * for testing.
@@ -303,6 +344,10 @@
             return addChild(new TestConfigurationContainer());
         }
 
+        TestConfigurationContainer addConstraintChild() {
+            return addChild(new TestConfigurationContainerWithConstraints());
+        }
+
         void removeChild(TestConfigurationContainer child) {
             child.mParent = null;
             child.onParentChanged();
@@ -324,12 +369,35 @@
         }
     }
 
+    /**
+     * Contains minimal implementation of {@link ConfigurationContainer}'s abstract behavior needed
+     * for testing.
+     */
+    private class TestConfigurationContainerWithConstraints
+            extends TestConfigurationContainer {
+
+        @Override
+        public void resolveOverrideConfiguration(Configuration newParentConfig) {
+            // Restrict smallestScreenWidthDp to 100
+            getResolvedOverrideConfiguration().setTo(getRequestedOverrideConfiguration());
+            int smallestScreenWidthDp =
+                    getResolvedOverrideConfiguration().smallestScreenWidthDp
+                            == SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
+                    ? newParentConfig.smallestScreenWidthDp
+                        : getResolvedOverrideConfiguration().smallestScreenWidthDp;
+            if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
+                getResolvedOverrideConfiguration().smallestScreenWidthDp =
+                        Math.min(smallestScreenWidthDp, 100);
+            }
+        }
+    }
+
     private static class TestConfigurationChangeListener implements ConfigurationContainerListener {
 
         final Configuration mOverrideConfiguration = new Configuration();
 
         @Override
-        public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+        public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
             mOverrideConfiguration.setTo(overrideConfiguration);
         }
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 3b8d71d..7c83ecc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -227,7 +227,8 @@
      */
     @Test
     public void testDisplayOverrideConfigUpdate() {
-        final Configuration currentOverrideConfig = mDisplayContent.getOverrideConfiguration();
+        final Configuration currentOverrideConfig =
+                mDisplayContent.getRequestedOverrideConfiguration();
 
         // Create new, slightly changed override configuration and apply it to the display.
         final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
@@ -237,7 +238,7 @@
         mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
 
         // Check that override config is applied.
-        assertEquals(newOverrideConfig, mDisplayContent.getOverrideConfiguration());
+        assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
     }
 
     /**
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 3c7b4b1..3e025f6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -875,8 +875,8 @@
         }
 
         @Override
-        void initRootActivityContainerMocks(WindowManagerService wm) {
-            super.initRootActivityContainerMocks(wm);
+        void createDefaultDisplay() {
+            super.createDefaultDisplay();
             mDisplay = mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY);
             mOtherDisplay = TestActivityDisplay.create(mTestStackSupervisor, DEFAULT_DISPLAY + 1);
             mRootActivityContainer.addChild(mOtherDisplay, ActivityDisplay.POSITION_TOP);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 105f826..fe632d4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -949,10 +949,11 @@
 
     @Test
     public void testAdjustBoundsToFitNewDisplay_LargerThanDisplay_RTL() {
-        final Configuration overrideConfig = mRootActivityContainer.getOverrideConfiguration();
+        final Configuration overrideConfig =
+                mRootActivityContainer.getRequestedOverrideConfiguration();
         // Egyptian Arabic is a RTL language.
         overrideConfig.setLayoutDirection(new Locale("ar", "EG"));
-        mRootActivityContainer.onOverrideConfigurationChanged(overrideConfig);
+        mRootActivityContainer.onRequestedOverrideConfigurationChanged(overrideConfig);
 
         final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
                 WINDOWING_MODE_FREEFORM);
diff --git a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 612f9ad..8854ede 100644
--- a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -49,7 +49,7 @@
         mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(token);
 
         // Make sure our handler processed the message.
-        SystemClock.sleep(100);
+        mWm.mH.runWithScissors(() -> { }, 0);
         assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
     }
 
@@ -65,7 +65,7 @@
         mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(token2);
 
         // Make sure our handler processed the message.
-        SystemClock.sleep(100);
+        mWm.mH.runWithScissors(() -> { }, 0);
         assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
index 7592f1c..de3567e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
@@ -93,19 +93,19 @@
 
         controller.setContainer(container);
         assertEquals(controller.mContainer, container);
-        assertEquals(EMPTY, container.getOverrideConfiguration());
+        assertEquals(EMPTY, container.getRequestedOverrideConfiguration());
 
         final Configuration config = new Configuration();
         config.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
         config.windowConfiguration.setAppBounds(10, 10, 10, 10);
 
         // Assert that the config change through the controller is propagated to the container.
-        controller.onOverrideConfigurationChanged(config);
-        assertEquals(config, container.getOverrideConfiguration());
+        controller.onRequestedOverrideConfigurationChanged(config);
+        assertEquals(config, container.getRequestedOverrideConfiguration());
 
         // Assert the container configuration isn't changed after removal from the controller.
         controller.removeContainer();
-        controller.onOverrideConfigurationChanged(EMPTY);
-        assertEquals(config, container.getOverrideConfiguration());
+        controller.onRequestedOverrideConfigurationChanged(EMPTY);
+        assertEquals(config, container.getRequestedOverrideConfiguration());
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index d4a32cf..60f957f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -424,7 +424,7 @@
 
         final TestWindowContainer parent = grandparent.addChildWindow();
         final TestWindowContainer child = parent.addChildWindow();
-        child.onOverrideConfigurationChanged(new Configuration());
+        child.onRequestedOverrideConfigurationChanged(new Configuration());
 
         assertTrue(grandparent.mOnDescendantOverrideCalled);
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 60a8aeb..d9ef10d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -96,7 +96,7 @@
         }
 
         @Override
-        public void getOverrideBounds(Rect outBounds) {
+        public void getRequestedOverrideBounds(Rect outBounds) {
             outBounds.set(mBounds);
         }
         @Override
@@ -448,9 +448,9 @@
         final int xInset = logicalWidth / 10;
         final int yInset = logicalWidth / 10;
         final Rect cf = new Rect(xInset, yInset, logicalWidth - xInset, logicalHeight - yInset);
-        Configuration config = new Configuration(w.mAppToken.getOverrideConfiguration());
+        Configuration config = new Configuration(w.mAppToken.getRequestedOverrideConfiguration());
         config.windowConfiguration.setBounds(cf);
-        w.mAppToken.onOverrideConfigurationChanged(config);
+        w.mAppToken.onRequestedOverrideConfigurationChanged(config);
         pf.set(0, 0, logicalWidth, logicalHeight);
         task.mFullscreenForTest = true;
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRule.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRule.java
index 50fd188..522ab9f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRule.java
@@ -149,10 +149,9 @@
                 mService.onInitReady();
 
                 final Display display = mService.mDisplayManager.getDisplay(DEFAULT_DISPLAY);
-                final DisplayWindowController dcw = new DisplayWindowController(display, mService);
                 // Display creation is driven by the ActivityManagerService via
                 // ActivityStackSupervisor. We emulate those steps here.
-                mService.mRoot.createDisplayContent(display, dcw);
+                mService.mRoot.createDisplayContent(display, mock(ActivityDisplay.class));
             }
 
             private void removeServices() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index aa0ecf8..65e1835 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -58,8 +58,8 @@
     public static class TestDisplayContent extends DisplayContent {
 
         private TestDisplayContent(Display display, WindowManagerService service,
-                DisplayWindowController controller) {
-            super(display, service, controller);
+                ActivityDisplay activityDisplay) {
+            super(display, service, activityDisplay);
         }
 
         /**
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index b3f56e7..5c3368b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -339,7 +339,7 @@
             final int stackId = ++sNextStackId;
             final StackWindowController controller = new StackWindowController(stackId, null,
                     dc.getDisplayId(), true /* onTop */, new Rect(), mWm);
-            controller.onOverrideConfigurationChanged(overrideConfig);
+            controller.onRequestedOverrideConfigurationChanged(overrideConfig);
             return controller;
         }
     }
@@ -360,21 +360,17 @@
         final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
                 displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
         synchronized (mWm.mGlobalLock) {
-            return new DisplayContent(display, mWm, mock(DisplayWindowController.class));
+            return new DisplayContent(display, mWm, mock(ActivityDisplay.class));
         }
     }
 
     /**
      * Creates a {@link DisplayContent} with given display state and adds it to the system.
      *
-     * Unlike {@link #createNewDisplay()} that uses a mock {@link DisplayWindowController} to
-     * initialize {@link DisplayContent}, this method used real controller object when the test
-     * need to verify its related flows.
-     *
      * @param displayState For initializing the state of the display. See
      *                     {@link Display#getState()}.
      */
-    DisplayContent createNewDisplayWithController(int displayState) {
+    DisplayContent createNewDisplay(int displayState) {
         // Leverage main display info & initialize it with display state for given displayId.
         DisplayInfo displayInfo = new DisplayInfo();
         displayInfo.copyFrom(mDisplayInfo);
@@ -382,11 +378,11 @@
         final int displayId = sNextDisplayId++;
         final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
                 displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
-        final DisplayWindowController dcw = new DisplayWindowController(display, mWm);
         synchronized (mWm.mGlobalLock) {
             // Display creation is driven by DisplayWindowController via ActivityStackSupervisor.
             // We skip those steps here.
-            return mWm.mRoot.createDisplayContent(display, dcw);
+            final ActivityDisplay mockAd = mock(ActivityDisplay.class);
+            return mWm.mRoot.createDisplayContent(display, mockAd);
         }
     }
 
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 62cead1..0a60e34 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2361,6 +2361,32 @@
     public static final String KEY_CALL_WAITING_SERVICE_CLASS_INT =
             "call_waiting_service_class_int";
 
+    /**
+     * This configuration allow the system UI to display different 5G icon for different 5G status.
+     *
+     * There are four 5G status:
+     * 1. connected_mmwave: device currently connected to 5G cell as the secondary cell and using
+     *    millimeter wave.
+     * 2. connected: device currently connected to 5G cell as the secondary cell but not using
+     *    millimeter wave.
+     * 3. not_restricted: device camped on a network that has 5G capability(not necessary to connect
+     *    a 5G cell as a secondary cell) and the use of 5G is not restricted.
+     * 4. restricted: device camped on a network that has 5G capability(not necessary to connect a
+     *    5G cell as a secondary cell) but the use of 5G is restricted.
+     *
+     * The configured string contains multiple key-value pairs separated by comma. For each pair,
+     * the key and value is separated by a colon. The key is corresponded to a 5G status above and
+     * the value is the icon name. Use "None" as the icon name if no icon should be shown in a
+     * specific 5G status.
+     *
+     * Here is an example of the configuration:
+     * "connected_mmwave:5GPlus,connected:5G,not_restricted:None,restricted:None"
+     *
+     * @hide
+     */
+    public static final String KEY_5G_ICON_CONFIGURATION_STRING =
+            "5g_icon_configuration_string";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -2722,6 +2748,8 @@
         sDefaults.putBoolean(KEY_USE_CALL_FORWARDING_USSD_BOOL, false);
         sDefaults.putBoolean(KEY_USE_CALLER_ID_USSD_BOOL, false);
         sDefaults.putInt(KEY_CALL_WAITING_SERVICE_CLASS_INT, 1 /* SERVICE_CLASS_VOICE */);
+        sDefaults.putString(KEY_5G_ICON_CONFIGURATION_STRING,
+                "connected_mmwave:None,connected:5G,not_restricted:None,restricted:None");
     }
 
     /**
diff --git a/telephony/java/android/telephony/PhoneNumberRange.java b/telephony/java/android/telephony/PhoneNumberRange.java
index d65156f..dba803b 100644
--- a/telephony/java/android/telephony/PhoneNumberRange.java
+++ b/telephony/java/android/telephony/PhoneNumberRange.java
@@ -71,10 +71,10 @@
     public PhoneNumberRange(@NonNull String countryCode, @NonNull String prefix,
             @NonNull String lowerBound, @NonNull String upperBound) {
         validateLowerAndUpperBounds(lowerBound, upperBound);
-        if (!Pattern.matches("[0-9]+", countryCode)) {
+        if (!Pattern.matches("[0-9]*", countryCode)) {
             throw new IllegalArgumentException("Country code must be all numeric");
         }
-        if (!Pattern.matches("[0-9]+", prefix)) {
+        if (!Pattern.matches("[0-9]*", prefix)) {
             throw new IllegalArgumentException("Prefix must be all numeric");
         }
         mCountryCode = countryCode;
@@ -133,10 +133,10 @@
         if (lowerBound.length() != upperBound.length()) {
             throw new IllegalArgumentException("Lower and upper bounds must have the same length");
         }
-        if (!Pattern.matches("[0-9]+", lowerBound)) {
+        if (!Pattern.matches("[0-9]*", lowerBound)) {
             throw new IllegalArgumentException("Lower bound must be all numeric");
         }
-        if (!Pattern.matches("[0-9]+", upperBound)) {
+        if (!Pattern.matches("[0-9]*", upperBound)) {
             throw new IllegalArgumentException("Upper bound must be all numeric");
         }
         if (Integer.parseInt(lowerBound) > Integer.parseInt(upperBound)) {
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index ca0c854a..7c52d38 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -27,6 +27,7 @@
 import android.os.Parcelable;
 import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.NetworkRegistrationState.Domain;
+import android.telephony.NetworkRegistrationState.NRStatus;
 import android.text.TextUtils;
 
 import java.lang.annotation.Retention;
@@ -1358,6 +1359,18 @@
     }
 
     /**
+     * Get the NR 5G status of the mobile data network.
+     * @return the NR 5G status.
+     * @hide
+     */
+    public @NRStatus int getNrStatus() {
+        final NetworkRegistrationState regState = getNetworkRegistrationState(
+                NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+        if (regState == null) return NetworkRegistrationState.NR_STATUS_NONE;
+        return regState.getNrStatus();
+    }
+
+    /**
      * @param nrFrequencyRange the frequency range of 5G NR.
      * @hide
      */
@@ -1531,7 +1544,6 @@
         }
     }
 
-
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public @TelephonyManager.NetworkType int getDataNetworkType() {
diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java
index b917fbd..0ac35bc 100644
--- a/test-mock/src/android/test/mock/MockContentProvider.java
+++ b/test-mock/src/android/test/mock/MockContentProvider.java
@@ -54,10 +54,10 @@
      */
     private class InversionIContentProvider implements IContentProvider {
         @Override
-        public ContentProviderResult[] applyBatch(String callingPackage,
+        public ContentProviderResult[] applyBatch(String callingPackage, String authority,
                 ArrayList<ContentProviderOperation> operations)
                 throws RemoteException, OperationApplicationException {
-            return MockContentProvider.this.applyBatch(operations);
+            return MockContentProvider.this.applyBatch(authority, operations);
         }
 
         @Override
@@ -112,9 +112,9 @@
         }
 
         @Override
-        public Bundle call(String callingPackage, String method, String request, Bundle args)
-                throws RemoteException {
-            return MockContentProvider.this.call(method, request, args);
+        public Bundle call(String callingPackage, String authority, String method, String request,
+                Bundle args) throws RemoteException {
+            return MockContentProvider.this.call(authority, method, request, args);
         }
 
         @Override
diff --git a/test-mock/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java
index 112d7ee..fc2a464 100644
--- a/test-mock/src/android/test/mock/MockIContentProvider.java
+++ b/test-mock/src/android/test/mock/MockIContentProvider.java
@@ -80,7 +80,7 @@
     }
 
     @Override
-    public ContentProviderResult[] applyBatch(String callingPackage,
+    public ContentProviderResult[] applyBatch(String callingPackage, String authority,
             ArrayList<ContentProviderOperation> operations) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
@@ -103,8 +103,8 @@
     }
 
     @Override
-    public Bundle call(String callingPackage, String method, String request, Bundle args)
-            throws RemoteException {
+    public Bundle call(String callingPackage, String authority, String method, String request,
+            Bundle args) throws RemoteException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 132135d..9d1edbf 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -51,7 +51,6 @@
     liblog \
     liblzma \
     libnativehelper \
-    libnetdaidl \
     libpackagelistparser \
     libpcre2 \
     libselinux \
@@ -93,7 +92,6 @@
   liblog \
   libcutils \
   libnativehelper \
-  libnetdaidl \
   netd_aidl_interface-cpp
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
index b40921f..50aef1d 100644
--- a/tests/net/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -24,9 +24,9 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
 import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES;
@@ -46,7 +46,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.ArraySet;
 
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -457,6 +456,62 @@
         assertEquals(nc1, nc2);
     }
 
+    @Test
+    public void testSetNetworkSpecifierOnMultiTransportNc() {
+        // Sequence 1: Transport + Transport + NetworkSpecifier
+        NetworkCapabilities nc1 = new NetworkCapabilities();
+        nc1.addTransportType(TRANSPORT_CELLULAR).addTransportType(TRANSPORT_WIFI);
+        try {
+            nc1.setNetworkSpecifier(new StringNetworkSpecifier("specs"));
+            fail("Cannot set NetworkSpecifier on a NetworkCapability with multiple transports!");
+        } catch (IllegalStateException expected) {
+            // empty
+        }
+
+        // Sequence 2: Transport + NetworkSpecifier + Transport
+        NetworkCapabilities nc2 = new NetworkCapabilities();
+        nc2.addTransportType(TRANSPORT_CELLULAR).setNetworkSpecifier(
+                new StringNetworkSpecifier("specs"));
+        try {
+            nc2.addTransportType(TRANSPORT_WIFI);
+            fail("Cannot set NetworkSpecifier on a NetworkCapability with multiple transports!");
+        } catch (IllegalStateException expected) {
+            // empty
+        }
+    }
+
+    @Test
+    public void testSetTransportInfoOnMultiTransportNc() {
+        // Sequence 1: Transport + Transport + TransportInfo
+        NetworkCapabilities nc1 = new NetworkCapabilities();
+        nc1.addTransportType(TRANSPORT_CELLULAR).addTransportType(TRANSPORT_WIFI)
+                .setTransportInfo(new TransportInfo() {});
+
+        // Sequence 2: Transport + NetworkSpecifier + Transport
+        NetworkCapabilities nc2 = new NetworkCapabilities();
+        nc2.addTransportType(TRANSPORT_CELLULAR).setTransportInfo(new TransportInfo() {})
+                .addTransportType(TRANSPORT_WIFI);
+    }
+
+    @Test
+    public void testCombineTransportInfo() {
+        NetworkCapabilities nc1 = new NetworkCapabilities();
+        nc1.setTransportInfo(new TransportInfo() {
+            // empty
+        });
+        NetworkCapabilities nc2 = new NetworkCapabilities();
+        nc2.setTransportInfo(new TransportInfo() {
+            // empty
+        });
+
+        try {
+            nc1.combineCapabilities(nc2);
+            fail("Should not be able to combine NetworkCaabilities which contain TransportInfos");
+        } catch (IllegalStateException expected) {
+            // empty
+        }
+    }
+
     private void assertEqualsThroughMarshalling(NetworkCapabilities netCap) {
         Parcel p = Parcel.obtain();
         netCap.writeToParcel(p, /* flags */ 0);
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index d6dbf5a..1e3a49b 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -448,22 +448,58 @@
     }
 
     @Test
-    public void testWithoutUid() throws Exception {
-        final NetworkStats before = new NetworkStats(TEST_START, 3)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 64L, 4L, 0L, 0L, 0L)
-                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 512L, 32L, 0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 128L, 8L, 0L, 0L, 0L);
+    public void testRemoveUids() throws Exception {
+        final NetworkStats before = new NetworkStats(TEST_START, 3);
 
-        final NetworkStats after = before.withoutUids(new int[] { 100 });
-        assertEquals(6, before.size());
-        assertEquals(2, after.size());
-        assertValues(after, 0, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L);
-        assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
-                DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L);
+        // Test 0 item stats.
+        NetworkStats after = before.clone();
+        after.removeUids(new int[0]);
+        assertEquals(0, after.size());
+        after.removeUids(new int[] {100});
+        assertEquals(0, after.size());
+
+        // Test 1 item stats.
+        before.addValues(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, 1L, 128L, 0L, 2L, 20L);
+        after = before.clone();
+        after.removeUids(new int[0]);
+        assertEquals(1, after.size());
+        assertValues(after, 0, TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 1L, 128L, 0L, 2L, 20L);
+        after.removeUids(new int[] {99});
+        assertEquals(0, after.size());
+
+        // Append remaining test items.
+        before.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 2L, 64L, 0L, 2L, 20L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 4L, 32L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 16L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 8L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 4L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 64L, 2L, 0L, 0L, 0L);
+        assertEquals(7, before.size());
+
+        // Test remove with empty uid list.
+        after = before.clone();
+        after.removeUids(new int[0]);
+        assertValues(after.getTotalIncludingTags(null), 127L, 254L, 0L, 4L, 40L);
+
+        // Test remove uids don't exist in stats.
+        after.removeUids(new int[] {98, 0, Integer.MIN_VALUE, Integer.MAX_VALUE});
+        assertValues(after.getTotalIncludingTags(null), 127L, 254L, 0L, 4L, 40L);
+
+        // Test remove all uids.
+        after.removeUids(new int[] {99, 100, 100, 101});
+        assertEquals(0, after.size());
+
+        // Test remove in the middle.
+        after = before.clone();
+        after.removeUids(new int[] {100});
+        assertEquals(3, after.size());
+        assertValues(after, 0, TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 1L, 128L, 0L, 2L, 20L);
+        assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 32L, 4L, 0L, 0L, 0L);
+        assertValues(after, 2, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 64L, 2L, 0L, 0L, 0L);
     }
 
     @Test
diff --git a/tests/net/java/android/net/ip/IpClientTest.java b/tests/net/java/android/net/ip/IpClientTest.java
index 5a8d2cd..cba3c65 100644
--- a/tests/net/java/android/net/ip/IpClientTest.java
+++ b/tests/net/java/android/net/ip/IpClientTest.java
@@ -81,7 +81,7 @@
     private static final int TEST_IFINDEX = 1001;
     // See RFC 7042#section-2.1.2 for EUI-48 documentation values.
     private static final MacAddress TEST_MAC = MacAddress.fromString("00:00:5E:00:53:01");
-    private static final int TEST_TIMEOUT_MS = 200;
+    private static final int TEST_TIMEOUT_MS = 400;
 
     @Mock private Context mContext;
     @Mock private INetworkManagementService mNMService;