Merge "Added edge swipe support for along nav bar direction"
diff --git a/api/current.txt b/api/current.txt
index f6f5476..784f454 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);
@@ -36000,6 +36030,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";
   }
 
@@ -36028,6 +36059,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 {
@@ -36119,6 +36151,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";
@@ -37364,26 +37400,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.os.Bundle getDocumentMetadata(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException;
-    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.ContentResolver, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
+    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";
@@ -53252,7 +53288,7 @@
     method public abstract boolean getDomStorageEnabled();
     method public abstract java.lang.String getFantasyFontFamily();
     method public abstract java.lang.String getFixedFontFamily();
-    method public abstract int getForceDarkMode();
+    method public int getForceDarkMode();
     method public abstract boolean getJavaScriptCanOpenWindowsAutomatically();
     method public abstract boolean getJavaScriptEnabled();
     method public abstract android.webkit.WebSettings.LayoutAlgorithm getLayoutAlgorithm();
@@ -53299,7 +53335,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 abstract void setForceDarkMode(int);
+    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);
diff --git a/api/system-current.txt b/api/system-current.txt
index 57b7eed..9873c37 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2925,6 +2925,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);
@@ -2945,7 +2952,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[]);
   }
 
 }
@@ -3035,7 +3042,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);
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 46cbb52..b6a42ec 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -299,7 +299,7 @@
 
 package android.content {
 
-  public abstract class ContentResolver {
+  public abstract class ContentResolver implements android.content.ContentInterface {
     method public static java.lang.String[] getSyncAdapterPackagesForAuthorityAsUser(java.lang.String, int);
   }
 
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/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index cfda803..61b9d55 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -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/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/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index e826250..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;
 
@@ -2032,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.
@@ -9897,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}.
@@ -9906,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
@@ -9913,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/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 0f72fd3..5a12e4e 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -105,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";
 
@@ -324,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();
@@ -356,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) {
@@ -444,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);
@@ -1255,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;
@@ -1293,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);
 
     /**
@@ -1325,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;
     }
@@ -1343,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;
     }
@@ -1369,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;
@@ -1403,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);
 
     /**
@@ -1420,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++) {
@@ -1448,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);
 
@@ -1468,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);
 
@@ -1604,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);
@@ -1723,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);
@@ -1789,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;
     }
@@ -1905,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 {
@@ -2059,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 {
@@ -2088,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;
@@ -2133,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 {
@@ -2144,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..cd7a1a1 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -65,7 +65,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 +76,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,12 +87,20 @@
 
     /** {@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");
@@ -153,6 +162,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 +193,7 @@
     }
 
     /** See {@link ContentProvider#getType ContentProvider.getType} */
+    @Override
     public @Nullable String getType(@NonNull Uri url) throws RemoteException {
         Preconditions.checkNotNull(url, "url");
 
@@ -200,6 +211,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 +231,7 @@
     }
 
     /** See {@link ContentProvider#canonicalize} */
+    @Override
     public final @Nullable Uri canonicalize(@NonNull Uri url) throws RemoteException {
         Preconditions.checkNotNull(url, "url");
 
@@ -236,6 +249,7 @@
     }
 
     /** See {@link ContentProvider#uncanonicalize} */
+    @Override
     public final @Nullable Uri uncanonicalize(@NonNull Uri url) throws RemoteException {
         Preconditions.checkNotNull(url, "url");
 
@@ -253,6 +267,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 +292,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 +311,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 +331,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 +350,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 +387,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 +431,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 +467,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 +486,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 +500,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 +527,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/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/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/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/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index a8f3665..92fe028 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 4737577..ff77228 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -24,7 +24,7 @@
 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;
@@ -48,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;
@@ -68,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
  */
@@ -234,11 +233,6 @@
     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";
@@ -381,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)
@@ -407,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;
@@ -445,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;
@@ -456,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;
@@ -466,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;
@@ -490,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;
@@ -684,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;
@@ -807,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";
@@ -1255,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.
      *
@@ -1289,33 +1267,24 @@
      * @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
@@ -1326,39 +1295,29 @@
      * @return if given document is a descendant of the given parent.
      * @see Root#FLAG_SUPPORTS_IS_CHILD
      */
-    public static boolean isChildDocument(ContentResolver resolver, Uri parentDocumentUri,
+    public static boolean isChildDocument(ContentInterface content, Uri parentDocumentUri,
             Uri childDocumentUri) throws FileNotFoundException {
-        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
-                parentDocumentUri.getAuthority());
         try {
-            return isChildDocument(client, parentDocumentUri, childDocumentUri);
+            final Bundle in = new Bundle();
+            in.putParcelable(DocumentsContract.EXTRA_URI, parentDocumentUri);
+            in.putParcelable(DocumentsContract.EXTRA_TARGET_URI, childDocumentUri);
+
+            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 query isChildDocument", e);
-            rethrowIfNecessary(resolver, e);
+            Log.w(TAG, "Failed to create document", e);
+            rethrowIfNecessary(e);
             return false;
-        } finally {
-            ContentProviderClient.releaseQuietly(client);
         }
     }
 
-    /** {@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 response from isChildDocument query.");
-        }
-        if (!out.containsKey(DocumentsContract.EXTRA_RESULT)) {
-            throw new RemoteException("Response did not include result field..");
-        }
-        return out.getBoolean(DocumentsContract.EXTRA_RESULT);
-    }
-
     /**
      * Change the display name of an existing document.
      * <p>
@@ -1372,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.
      *
@@ -1438,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.
      *
@@ -1473,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.
      *
@@ -1512,58 +1433,40 @@
      * @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
@@ -1594,67 +1497,22 @@
      * @param documentUri a Document URI
      * @return a Bundle of Bundles.
      */
-    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
@@ -1667,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
@@ -1763,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.
@@ -1836,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/Settings.java b/core/java/android/provider/Settings.java
index f86296b8..3437e1d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2055,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;
@@ -2128,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);
@@ -5123,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);
             }
@@ -11874,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.
@@ -13158,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);
             }
@@ -13953,7 +13974,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/augmented/FillWindow.java b/core/java/android/service/autofill/augmented/FillWindow.java
index 9e3aba4..27df845 100644
--- a/core/java/android/service/autofill/augmented/FillWindow.java
+++ b/core/java/android/service/autofill/augmented/FillWindow.java
@@ -26,6 +26,7 @@
 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;
@@ -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;
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/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index ca8da55..da6e208 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -417,16 +417,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;
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 594ae6b..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. -->
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 1d72a03..79eaab8 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -470,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,
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/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/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 4805780..9038f72 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -1711,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;
         }
@@ -2398,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) {
@@ -2426,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;
                     }
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/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 5a9a7c8..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);
     }
 
     /**
diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index d087176..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,7 +105,8 @@
     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 zoneId, int groupId, int flags) {
             // TODO: Include zoneId into consideration.
@@ -162,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);
             }
@@ -440,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/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/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/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 5e7fb85..533956f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -685,8 +685,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);
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/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/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/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/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 61eb9d4..0301a5b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -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/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 bca3b1f..041d5d8 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;
@@ -13280,32 +13282,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/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/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/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index ca0c854..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");
     }