Merge "Unhide isRttSupported in TelephonyManager"
diff --git a/Android.bp b/Android.bp
index 225f86de..fcea5d0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -221,6 +221,7 @@
         "core/java/android/os/ICancellationSignal.aidl",
         "core/java/android/os/IDeviceIdentifiersPolicyService.aidl",
         "core/java/android/os/IDeviceIdleController.aidl",
+        "core/java/android/os/IDynamicAndroidService.aidl",
         "core/java/android/os/IHardwarePropertiesManager.aidl",
         ":libincident_aidl",
         "core/java/android/os/IMaintenanceActivityListener.aidl",
@@ -601,6 +602,7 @@
 
         ":storaged_aidl",
         ":vold_aidl",
+        ":gsiservice_aidl",
         ":installd_aidl",
         ":dumpstate_aidl",
 
@@ -657,6 +659,7 @@
             "frameworks/native/aidl/gui",
             "system/core/storaged/binder",
             "system/vold/binder",
+            "system/gsid/aidl",
             "system/bt/binder",
             "system/security/keystore/binder",
         ],
@@ -851,6 +854,7 @@
         "core/java/android/annotation/UnsupportedAppUsage.java",
         "core/java/android/net/DhcpResults.java",
         "core/java/android/util/LocalLog.java",
+        "core/java/com/android/internal/annotations/GuardedBy.java",
         "core/java/com/android/internal/annotations/VisibleForTesting.java",
         "core/java/com/android/internal/util/HexDump.java",
         "core/java/com/android/internal/util/IndentingPrintWriter.java",
diff --git a/Android.mk b/Android.mk
index e405345..65d4d24 100644
--- a/Android.mk
+++ b/Android.mk
@@ -78,6 +78,7 @@
 update-api: doc-comment-check-docs
 
 # ==== hiddenapi lists =======================================
+ifneq ($(UNSAFE_DISABLE_HIDDENAPI_FLAGS),true)
 .KATI_RESTAT: $(INTERNAL_PLATFORM_HIDDENAPI_FLAGS)
 $(INTERNAL_PLATFORM_HIDDENAPI_FLAGS): \
     PRIVATE_FLAGS_INPUTS := $(PRIVATE_FLAGS_INPUTS) $(SOONG_HIDDENAPI_FLAGS)
@@ -108,6 +109,7 @@
 
 $(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_FLAGS))
 $(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA))
+endif  # UNSAFE_DISABLE_HIDDENAPI_FLAGS
 
 # Include subdirectory makefiles
 # ============================================================
diff --git a/api/current.txt b/api/current.txt
index e7da1bd..c386819 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -11200,7 +11200,7 @@
     method public abstract java.util.List<android.content.pm.PermissionGroupInfo> getAllPermissionGroups(int);
     method public abstract android.graphics.drawable.Drawable getApplicationBanner(android.content.pm.ApplicationInfo);
     method public abstract android.graphics.drawable.Drawable getApplicationBanner(String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public abstract int getApplicationEnabledSetting(String);
+    method public abstract int getApplicationEnabledSetting(@NonNull String);
     method public abstract android.graphics.drawable.Drawable getApplicationIcon(android.content.pm.ApplicationInfo);
     method public abstract android.graphics.drawable.Drawable getApplicationIcon(String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.pm.ApplicationInfo getApplicationInfo(String, int) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -11208,7 +11208,7 @@
     method public abstract android.graphics.drawable.Drawable getApplicationLogo(android.content.pm.ApplicationInfo);
     method public abstract android.graphics.drawable.Drawable getApplicationLogo(String) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Nullable public abstract android.content.pm.ChangedPackages getChangedPackages(@IntRange(from=0) int);
-    method public abstract int getComponentEnabledSetting(android.content.ComponentName);
+    method public abstract int getComponentEnabledSetting(@NonNull android.content.ComponentName);
     method public abstract android.graphics.drawable.Drawable getDefaultActivityIcon();
     method public abstract android.graphics.drawable.Drawable getDrawable(String, @DrawableRes int, android.content.pm.ApplicationInfo);
     method public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
@@ -11271,8 +11271,8 @@
     method public abstract android.content.pm.ProviderInfo resolveContentProvider(String, int);
     method public abstract android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
     method public abstract void setApplicationCategoryHint(@NonNull String, int);
-    method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public abstract void setApplicationEnabledSetting(String, int, int);
-    method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public abstract void setComponentEnabledSetting(android.content.ComponentName, int, int);
+    method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public abstract void setApplicationEnabledSetting(@NonNull String, int, int);
+    method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public abstract void setComponentEnabledSetting(@NonNull android.content.ComponentName, int, int);
     method public abstract void setInstallerPackageName(String, String);
     method public abstract void updateInstantAppCookie(@Nullable byte[]);
     method public abstract void verifyPendingInstall(int, int);
@@ -27854,6 +27854,7 @@
     method public android.net.VpnService.Builder setBlocking(boolean);
     method public android.net.VpnService.Builder setConfigureIntent(android.app.PendingIntent);
     method public android.net.VpnService.Builder setHttpProxy(android.net.ProxyInfo);
+    method public android.net.VpnService.Builder setMetered(boolean);
     method public android.net.VpnService.Builder setMtu(int);
     method public android.net.VpnService.Builder setSession(String);
     method public android.net.VpnService.Builder setUnderlyingNetworks(android.net.Network[]);
@@ -41156,6 +41157,7 @@
     method public static String capabilitiesToString(int);
     method public android.telecom.PhoneAccountHandle getAccountHandle();
     method public int getCallCapabilities();
+    method public int getCallDirection();
     method @Nullable public android.telecom.CallIdentification getCallIdentification();
     method public int getCallProperties();
     method public String getCallerDisplayName();
@@ -41192,6 +41194,9 @@
     field public static final int CAPABILITY_SUPPORT_DEFLECT = 16777216; // 0x1000000
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
+    field public static final int DIRECTION_INCOMING = 0; // 0x0
+    field public static final int DIRECTION_OUTGOING = 1; // 0x1
+    field public static final int DIRECTION_UNKNOWN = -1; // 0xffffffff
     field public static final int PROPERTY_CONFERENCE = 1; // 0x1
     field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4
     field public static final int PROPERTY_ENTERPRISE_CALL = 32; // 0x20
@@ -41858,12 +41863,12 @@
 
   public class TelecomManager {
     method public void acceptHandover(android.net.Uri, int, android.telecom.PhoneAccountHandle);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall();
-    method @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall(int);
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall();
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall(int);
     method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void cancelMissedCallsNotification();
     method public android.content.Intent createManageBlockedNumbersIntent();
-    method @RequiresPermission(android.Manifest.permission.ANSWER_PHONE_CALLS) public boolean endCall();
+    method @Deprecated @RequiresPermission(android.Manifest.permission.ANSWER_PHONE_CALLS) public boolean endCall();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.net.Uri getAdnUriForPhoneAccount(android.telecom.PhoneAccountHandle);
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts();
     method public String getDefaultDialerPackage();
@@ -43093,8 +43098,10 @@
     method public boolean setVoiceMailNumber(String, String);
     method @Deprecated public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
     method @Deprecated public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void switchMultiSimConfig(int);
     method public boolean updateAvailableNetworks(java.util.List<android.telephony.AvailableNetworkInfo>);
     field public static final String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
+    field public static final String ACTION_NETWORK_COUNTRY_CHANGED = "android.telephony.action.NETWORK_COUNTRY_CHANGED";
     field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
     field public static final String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
     field public static final String ACTION_SECRET_CODE = "android.telephony.action.SECRET_CODE";
@@ -43132,6 +43139,7 @@
     field public static final String EXTRA_INCOMING_NUMBER = "incoming_number";
     field public static final String EXTRA_IS_REFRESH = "android.telephony.extra.IS_REFRESH";
     field public static final String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
+    field public static final String EXTRA_NETWORK_COUNTRY = "android.telephony.extra.NETWORK_COUNTRY";
     field public static final String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
     field public static final String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telephony.extra.PHONE_ACCOUNT_HANDLE";
     field public static final String EXTRA_PRECISE_CARRIER_ID = "android.telephony.extra.PRECISE_CARRIER_ID";
@@ -55533,13 +55541,13 @@
     ctor public ByteArrayOutputStream(int);
     method public void reset();
     method public int size();
-    method public byte[] toByteArray();
+    method @NonNull public byte[] toByteArray();
     method @NonNull public String toString(@NonNull String) throws java.io.UnsupportedEncodingException;
     method @Deprecated @NonNull public String toString(int);
     method public void write(int);
-    method public void write(byte[], int, int);
+    method public void write(@NonNull byte[], int, int);
     method public void writeTo(@NonNull java.io.OutputStream) throws java.io.IOException;
-    field protected byte[] buf;
+    field @NonNull protected byte[] buf;
     field protected int count;
   }
 
@@ -55710,12 +55718,12 @@
     method public boolean isHidden();
     method public long lastModified();
     method public long length();
-    method public String[] list();
-    method public String[] list(@Nullable java.io.FilenameFilter);
-    method public java.io.File[] listFiles();
-    method public java.io.File[] listFiles(@Nullable java.io.FilenameFilter);
-    method public java.io.File[] listFiles(@Nullable java.io.FileFilter);
-    method public static java.io.File[] listRoots();
+    method @Nullable public String[] list();
+    method @Nullable public String[] list(@Nullable java.io.FilenameFilter);
+    method @Nullable public java.io.File[] listFiles();
+    method @Nullable public java.io.File[] listFiles(@Nullable java.io.FilenameFilter);
+    method @Nullable public java.io.File[] listFiles(@Nullable java.io.FileFilter);
+    method @NonNull public static java.io.File[] listRoots();
     method public boolean mkdir();
     method public boolean mkdirs();
     method public boolean renameTo(@NonNull java.io.File);
@@ -56204,8 +56212,8 @@
     method protected void clearError();
     method public void close();
     method public void flush();
-    method @NonNull public java.io.PrintWriter format(@NonNull String, java.lang.Object...);
-    method @NonNull public java.io.PrintWriter format(@Nullable java.util.Locale, @NonNull String, java.lang.Object...);
+    method @NonNull public java.io.PrintWriter format(@NonNull String, @NonNull java.lang.Object...);
+    method @NonNull public java.io.PrintWriter format(@Nullable java.util.Locale, @NonNull String, @NonNull java.lang.Object...);
     method public void print(boolean);
     method public void print(char);
     method public void print(int);
@@ -56215,8 +56223,8 @@
     method public void print(char[]);
     method public void print(@Nullable String);
     method public void print(@Nullable Object);
-    method @NonNull public java.io.PrintWriter printf(@NonNull String, java.lang.Object...);
-    method @NonNull public java.io.PrintWriter printf(@Nullable java.util.Locale, @NonNull String, java.lang.Object...);
+    method @NonNull public java.io.PrintWriter printf(@NonNull String, @NonNull java.lang.Object...);
+    method @NonNull public java.io.PrintWriter printf(@Nullable java.util.Locale, @NonNull String, @NonNull java.lang.Object...);
     method public void println();
     method public void println(boolean);
     method public void println(char);
@@ -57042,45 +57050,45 @@
     method @NonNull public static Class<?> forName(@NonNull String) throws java.lang.ClassNotFoundException;
     method @NonNull public static Class<?> forName(@NonNull String, boolean, @Nullable ClassLoader) throws java.lang.ClassNotFoundException;
     method @Nullable public <A extends java.lang.annotation.Annotation> A getAnnotation(@NonNull Class<A>);
-    method public java.lang.annotation.Annotation[] getAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getAnnotations();
     method @NonNull public <A extends java.lang.annotation.Annotation> A[] getAnnotationsByType(@NonNull Class<A>);
     method @Nullable public String getCanonicalName();
     method @Nullable public ClassLoader getClassLoader();
-    method public Class<?>[] getClasses();
+    method @NonNull public Class<?>[] getClasses();
     method @Nullable public Class<?> getComponentType();
-    method @NonNull public java.lang.reflect.Constructor<T> getConstructor(Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
-    method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Constructor<T> getConstructor(@Nullable Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
     method @Nullable public <A extends java.lang.annotation.Annotation> A getDeclaredAnnotation(@NonNull Class<A>);
-    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
-    method public Class<?>[] getDeclaredClasses();
-    method @NonNull public java.lang.reflect.Constructor<T> getDeclaredConstructor(Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
-    method public java.lang.reflect.Constructor<?>[] getDeclaredConstructors() throws java.lang.SecurityException;
+    method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method @NonNull public Class<?>[] getDeclaredClasses();
+    method @NonNull public java.lang.reflect.Constructor<T> getDeclaredConstructor(@Nullable Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Constructor<?>[] getDeclaredConstructors() throws java.lang.SecurityException;
     method @NonNull public java.lang.reflect.Field getDeclaredField(@NonNull String) throws java.lang.NoSuchFieldException;
-    method public java.lang.reflect.Field[] getDeclaredFields();
-    method @NonNull public java.lang.reflect.Method getDeclaredMethod(@NonNull String, Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
-    method public java.lang.reflect.Method[] getDeclaredMethods() throws java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Field[] getDeclaredFields();
+    method @NonNull public java.lang.reflect.Method getDeclaredMethod(@NonNull String, @Nullable Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Method[] getDeclaredMethods() throws java.lang.SecurityException;
     method @Nullable public Class<?> getDeclaringClass();
     method @Nullable public Class<?> getEnclosingClass();
     method @Nullable public java.lang.reflect.Constructor<?> getEnclosingConstructor();
     method @Nullable public java.lang.reflect.Method getEnclosingMethod();
-    method public T[] getEnumConstants();
+    method @Nullable public T[] getEnumConstants();
     method @NonNull public java.lang.reflect.Field getField(@NonNull String) throws java.lang.NoSuchFieldException;
-    method public java.lang.reflect.Field[] getFields() throws java.lang.SecurityException;
-    method public java.lang.reflect.Type[] getGenericInterfaces();
+    method @NonNull public java.lang.reflect.Field[] getFields() throws java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Type[] getGenericInterfaces();
     method @Nullable public java.lang.reflect.Type getGenericSuperclass();
-    method public Class<?>[] getInterfaces();
-    method @NonNull public java.lang.reflect.Method getMethod(@NonNull String, Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
-    method public java.lang.reflect.Method[] getMethods() throws java.lang.SecurityException;
+    method @NonNull public Class<?>[] getInterfaces();
+    method @NonNull public java.lang.reflect.Method getMethod(@NonNull String, @Nullable Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Method[] getMethods() throws java.lang.SecurityException;
     method public int getModifiers();
     method @NonNull public String getName();
     method @Nullable public Package getPackage();
     method @Nullable public java.security.ProtectionDomain getProtectionDomain();
     method @Nullable public java.net.URL getResource(@NonNull String);
     method @Nullable public java.io.InputStream getResourceAsStream(@NonNull String);
-    method public Object[] getSigners();
+    method @Nullable public Object[] getSigners();
     method @NonNull public String getSimpleName();
     method @Nullable public Class<? super T> getSuperclass();
-    method public java.lang.reflect.TypeVariable<java.lang.Class<T>>[] getTypeParameters();
+    method @NonNull public java.lang.reflect.TypeVariable<java.lang.Class<T>>[] getTypeParameters();
     method public boolean isAnnotation();
     method public boolean isAnonymousClass();
     method public boolean isArray();
@@ -57967,8 +57975,8 @@
     method @NonNull public static String copyValueOf(char[]);
     method public boolean endsWith(@NonNull String);
     method public boolean equalsIgnoreCase(@Nullable String);
-    method @NonNull public static String format(@NonNull String, java.lang.Object...);
-    method @NonNull public static String format(@NonNull java.util.Locale, @NonNull String, java.lang.Object...);
+    method @NonNull public static String format(@NonNull String, @NonNull java.lang.Object...);
+    method @NonNull public static String format(@NonNull java.util.Locale, @NonNull String, @NonNull java.lang.Object...);
     method @Deprecated public void getBytes(int, int, byte[], int);
     method public byte[] getBytes(@NonNull String) throws java.io.UnsupportedEncodingException;
     method public byte[] getBytes(@NonNull java.nio.charset.Charset);
@@ -57980,7 +57988,7 @@
     method public int indexOf(@NonNull String, int);
     method @NonNull public String intern();
     method public boolean isEmpty();
-    method @NonNull public static String join(@NonNull CharSequence, java.lang.CharSequence...);
+    method @NonNull public static String join(@NonNull CharSequence, @Nullable java.lang.CharSequence...);
     method @NonNull public static String join(@NonNull CharSequence, @NonNull Iterable<? extends java.lang.CharSequence>);
     method public int lastIndexOf(int);
     method public int lastIndexOf(int, int);
@@ -57995,8 +58003,8 @@
     method @NonNull public String replace(@NonNull CharSequence, @NonNull CharSequence);
     method @NonNull public String replaceAll(@NonNull String, @NonNull String);
     method @NonNull public String replaceFirst(@NonNull String, @NonNull String);
-    method public String[] split(@NonNull String, int);
-    method public String[] split(@NonNull String);
+    method @NonNull public String[] split(@NonNull String, int);
+    method @NonNull public String[] split(@NonNull String);
     method public boolean startsWith(@NonNull String, int);
     method public boolean startsWith(@NonNull String);
     method @NonNull public CharSequence subSequence(int, int);
@@ -58197,7 +58205,7 @@
     method public long getId();
     method @NonNull public final String getName();
     method public final int getPriority();
-    method public StackTraceElement[] getStackTrace();
+    method @NonNull public StackTraceElement[] getStackTrace();
     method @NonNull public java.lang.Thread.State getState();
     method @Nullable public final ThreadGroup getThreadGroup();
     method @Nullable public java.lang.Thread.UncaughtExceptionHandler getUncaughtExceptionHandler();
@@ -58295,13 +58303,13 @@
     method @Nullable public Throwable getCause();
     method @Nullable public String getLocalizedMessage();
     method @Nullable public String getMessage();
-    method public StackTraceElement[] getStackTrace();
-    method public final Throwable[] getSuppressed();
+    method @NonNull public StackTraceElement[] getStackTrace();
+    method @NonNull public final Throwable[] getSuppressed();
     method @NonNull public Throwable initCause(@Nullable Throwable);
     method public void printStackTrace();
     method public void printStackTrace(@NonNull java.io.PrintStream);
     method public void printStackTrace(@NonNull java.io.PrintWriter);
-    method public void setStackTrace(StackTraceElement[]);
+    method public void setStackTrace(@NonNull StackTraceElement[]);
   }
 
   public class TypeNotPresentException extends java.lang.RuntimeException {
@@ -58624,8 +58632,8 @@
   public class AccessibleObject implements java.lang.reflect.AnnotatedElement {
     ctor protected AccessibleObject();
     method @Nullable public <T extends java.lang.annotation.Annotation> T getAnnotation(@NonNull Class<T>);
-    method public java.lang.annotation.Annotation[] getAnnotations();
-    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public boolean isAccessible();
     method public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean) throws java.lang.SecurityException;
     method public void setAccessible(boolean) throws java.lang.SecurityException;
@@ -58633,10 +58641,10 @@
 
   public interface AnnotatedElement {
     method @Nullable public <T extends java.lang.annotation.Annotation> T getAnnotation(@NonNull Class<T>);
-    method public java.lang.annotation.Annotation[] getAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getAnnotations();
     method public default <T extends java.lang.annotation.Annotation> T[] getAnnotationsByType(@NonNull Class<T>);
     method @Nullable public default <T extends java.lang.annotation.Annotation> T getDeclaredAnnotation(@NonNull Class<T>);
-    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public default <T extends java.lang.annotation.Annotation> T[] getDeclaredAnnotationsByType(@NonNull Class<T>);
     method public default boolean isAnnotationPresent(@NonNull Class<? extends java.lang.annotation.Annotation>);
   }
@@ -58671,20 +58679,20 @@
     method public int getModifiers();
     method @NonNull public String getName();
     method public java.lang.annotation.Annotation[][] getParameterAnnotations();
-    method public Class<?>[] getParameterTypes();
+    method @NonNull public Class<?>[] getParameterTypes();
     method public java.lang.reflect.TypeVariable<java.lang.reflect.Constructor<T>>[] getTypeParameters();
     method @NonNull public T newInstance(java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
     method @NonNull public String toGenericString();
   }
 
   public abstract class Executable extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
-    method public abstract Class<?>[] getExceptionTypes();
-    method public java.lang.reflect.Type[] getGenericExceptionTypes();
-    method public java.lang.reflect.Type[] getGenericParameterTypes();
-    method public abstract java.lang.annotation.Annotation[][] getParameterAnnotations();
+    method @NonNull public abstract Class<?>[] getExceptionTypes();
+    method @NonNull public java.lang.reflect.Type[] getGenericExceptionTypes();
+    method @NonNull public java.lang.reflect.Type[] getGenericParameterTypes();
+    method @NonNull public abstract java.lang.annotation.Annotation[][] getParameterAnnotations();
     method public int getParameterCount();
-    method public abstract Class<?>[] getParameterTypes();
-    method public java.lang.reflect.Parameter[] getParameters();
+    method @NonNull public abstract Class<?>[] getParameterTypes();
+    method @NonNull public java.lang.reflect.Parameter[] getParameters();
     method public final boolean isAnnotationPresent(@NonNull Class<? extends java.lang.annotation.Annotation>);
     method public boolean isSynthetic();
     method public boolean isVarArgs();
@@ -58773,7 +58781,7 @@
     method @NonNull public Class<?>[] getParameterTypes();
     method @NonNull public Class<?> getReturnType();
     method @NonNull public java.lang.reflect.TypeVariable<java.lang.reflect.Method>[] getTypeParameters();
-    method @Nullable public Object invoke(@Nullable Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
+    method @Nullable public Object invoke(@Nullable Object, @Nullable java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
     method public boolean isBridge();
     method public boolean isDefault();
     method @NonNull public String toGenericString();
@@ -58816,8 +58824,8 @@
 
   public final class Parameter implements java.lang.reflect.AnnotatedElement {
     method @Nullable public <T extends java.lang.annotation.Annotation> T getAnnotation(@NonNull Class<T>);
-    method public java.lang.annotation.Annotation[] getAnnotations();
-    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method @NonNull public java.lang.reflect.Executable getDeclaringExecutable();
     method public int getModifiers();
     method @NonNull public String getName();
@@ -58830,7 +58838,7 @@
   }
 
   public interface ParameterizedType extends java.lang.reflect.Type {
-    method public java.lang.reflect.Type[] getActualTypeArguments();
+    method @NonNull public java.lang.reflect.Type[] getActualTypeArguments();
     method @Nullable public java.lang.reflect.Type getOwnerType();
     method @NonNull public java.lang.reflect.Type getRawType();
   }
@@ -58838,9 +58846,9 @@
   public class Proxy implements java.io.Serializable {
     ctor protected Proxy(@NonNull java.lang.reflect.InvocationHandler);
     method @NonNull public static java.lang.reflect.InvocationHandler getInvocationHandler(@NonNull Object) throws java.lang.IllegalArgumentException;
-    method @NonNull public static Class<?> getProxyClass(@Nullable ClassLoader, Class<?>...) throws java.lang.IllegalArgumentException;
+    method @NonNull public static Class<?> getProxyClass(@Nullable ClassLoader, @NonNull Class<?>...) throws java.lang.IllegalArgumentException;
     method public static boolean isProxyClass(@NonNull Class<?>);
-    method @NonNull public static Object newProxyInstance(@Nullable ClassLoader, Class<?>[], @NonNull java.lang.reflect.InvocationHandler) throws java.lang.IllegalArgumentException;
+    method @NonNull public static Object newProxyInstance(@Nullable ClassLoader, @NonNull Class<?>[], @NonNull java.lang.reflect.InvocationHandler) throws java.lang.IllegalArgumentException;
     field protected java.lang.reflect.InvocationHandler h;
   }
 
@@ -58854,7 +58862,7 @@
   }
 
   public interface TypeVariable<D extends java.lang.reflect.GenericDeclaration> extends java.lang.reflect.Type {
-    method public java.lang.reflect.Type[] getBounds();
+    method @NonNull public java.lang.reflect.Type[] getBounds();
     method @NonNull public D getGenericDeclaration();
     method @NonNull public String getName();
   }
@@ -58866,8 +58874,8 @@
   }
 
   public interface WildcardType extends java.lang.reflect.Type {
-    method public java.lang.reflect.Type[] getLowerBounds();
-    method public java.lang.reflect.Type[] getUpperBounds();
+    method @NonNull public java.lang.reflect.Type[] getLowerBounds();
+    method @NonNull public java.lang.reflect.Type[] getUpperBounds();
   }
 
 }
@@ -59911,7 +59919,7 @@
   public abstract class ByteBuffer extends java.nio.Buffer implements java.lang.Comparable<java.nio.ByteBuffer> {
     method @NonNull public static java.nio.ByteBuffer allocate(int);
     method @NonNull public static java.nio.ByteBuffer allocateDirect(int);
-    method public final byte[] array();
+    method @NonNull public final byte[] array();
     method public final int arrayOffset();
     method @NonNull public abstract java.nio.CharBuffer asCharBuffer();
     method @NonNull public abstract java.nio.DoubleBuffer asDoubleBuffer();
@@ -59925,8 +59933,8 @@
     method @NonNull public abstract java.nio.ByteBuffer duplicate();
     method public abstract byte get();
     method public abstract byte get(int);
-    method @NonNull public java.nio.ByteBuffer get(byte[], int, int);
-    method @NonNull public java.nio.ByteBuffer get(byte[]);
+    method @NonNull public java.nio.ByteBuffer get(@NonNull byte[], int, int);
+    method @NonNull public java.nio.ByteBuffer get(@NonNull byte[]);
     method public abstract char getChar();
     method public abstract char getChar(int);
     method public abstract double getDouble();
@@ -59945,8 +59953,8 @@
     method @NonNull public abstract java.nio.ByteBuffer put(byte);
     method @NonNull public abstract java.nio.ByteBuffer put(int, byte);
     method @NonNull public java.nio.ByteBuffer put(@NonNull java.nio.ByteBuffer);
-    method @NonNull public java.nio.ByteBuffer put(byte[], int, int);
-    method @NonNull public final java.nio.ByteBuffer put(byte[]);
+    method @NonNull public java.nio.ByteBuffer put(@NonNull byte[], int, int);
+    method @NonNull public final java.nio.ByteBuffer put(@NonNull byte[]);
     method @NonNull public abstract java.nio.ByteBuffer putChar(char);
     method @NonNull public abstract java.nio.ByteBuffer putChar(int, char);
     method @NonNull public abstract java.nio.ByteBuffer putDouble(double);
@@ -59960,8 +59968,8 @@
     method @NonNull public abstract java.nio.ByteBuffer putShort(short);
     method @NonNull public abstract java.nio.ByteBuffer putShort(int, short);
     method @NonNull public abstract java.nio.ByteBuffer slice();
-    method @NonNull public static java.nio.ByteBuffer wrap(byte[], int, int);
-    method @NonNull public static java.nio.ByteBuffer wrap(byte[]);
+    method @NonNull public static java.nio.ByteBuffer wrap(@NonNull byte[], int, int);
+    method @NonNull public static java.nio.ByteBuffer wrap(@NonNull byte[]);
   }
 
   public final class ByteOrder {
@@ -61794,20 +61802,20 @@
 
   public abstract class MessageDigest extends java.security.MessageDigestSpi {
     ctor protected MessageDigest(@NonNull String);
-    method public byte[] digest();
-    method public int digest(byte[], int, int) throws java.security.DigestException;
-    method public byte[] digest(byte[]);
+    method @NonNull public byte[] digest();
+    method public int digest(@NonNull byte[], int, int) throws java.security.DigestException;
+    method @NonNull public byte[] digest(@NonNull byte[]);
     method @NonNull public final String getAlgorithm();
     method public final int getDigestLength();
     method @NonNull public static java.security.MessageDigest getInstance(@NonNull String) throws java.security.NoSuchAlgorithmException;
     method @NonNull public static java.security.MessageDigest getInstance(@NonNull String, @NonNull String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
     method @NonNull public static java.security.MessageDigest getInstance(@NonNull String, @NonNull java.security.Provider) throws java.security.NoSuchAlgorithmException;
     method @NonNull public final java.security.Provider getProvider();
-    method public static boolean isEqual(byte[], byte[]);
+    method public static boolean isEqual(@Nullable byte[], @Nullable byte[]);
     method public void reset();
     method public void update(byte);
-    method public void update(byte[], int, int);
-    method public void update(byte[]);
+    method public void update(@NonNull byte[], int, int);
+    method public void update(@NonNull byte[]);
     method public final void update(@NonNull java.nio.ByteBuffer);
   }
 
@@ -64414,7 +64422,7 @@
     method @NonNull public final StringBuffer format(@NonNull Object, @NonNull StringBuffer, @NonNull java.text.FieldPosition);
     method @NonNull public abstract StringBuffer format(@NonNull java.util.Date, @NonNull StringBuffer, @NonNull java.text.FieldPosition);
     method @NonNull public final String format(@NonNull java.util.Date);
-    method public static java.util.Locale[] getAvailableLocales();
+    method @NonNull public static java.util.Locale[] getAvailableLocales();
     method @NonNull public java.util.Calendar getCalendar();
     method @NonNull public static final java.text.DateFormat getDateInstance();
     method @NonNull public static final java.text.DateFormat getDateInstance(int);
@@ -64654,7 +64662,7 @@
     method @NonNull public final String format(long);
     method @NonNull public abstract StringBuffer format(double, @NonNull StringBuffer, @NonNull java.text.FieldPosition);
     method @NonNull public abstract StringBuffer format(long, @NonNull StringBuffer, @NonNull java.text.FieldPosition);
-    method public static java.util.Locale[] getAvailableLocales();
+    method @NonNull public static java.util.Locale[] getAvailableLocales();
     method @Nullable public java.util.Currency getCurrency();
     method @NonNull public static final java.text.NumberFormat getCurrencyInstance();
     method @NonNull public static java.text.NumberFormat getCurrencyInstance(@NonNull java.util.Locale);
@@ -66308,8 +66316,8 @@
     method public boolean remove(@Nullable Object);
     method public boolean removeAll(@NonNull java.util.Collection<?>);
     method public boolean retainAll(@NonNull java.util.Collection<?>);
-    method public Object[] toArray();
-    method public <T> T[] toArray(T[]);
+    method @NonNull public Object[] toArray();
+    method @NonNull public <T> T[] toArray(@NonNull T[]);
   }
 
   public abstract class AbstractList<E> extends java.util.AbstractCollection<E> implements java.util.List<E> {
@@ -66418,161 +66426,161 @@
   }
 
   public class Arrays {
-    method @NonNull @java.lang.SafeVarargs public static <T> java.util.List<T> asList(T...);
-    method public static int binarySearch(long[], long);
-    method public static int binarySearch(long[], int, int, long);
-    method public static int binarySearch(int[], int);
-    method public static int binarySearch(int[], int, int, int);
-    method public static int binarySearch(short[], short);
-    method public static int binarySearch(short[], int, int, short);
-    method public static int binarySearch(char[], char);
-    method public static int binarySearch(char[], int, int, char);
-    method public static int binarySearch(byte[], byte);
-    method public static int binarySearch(byte[], int, int, byte);
-    method public static int binarySearch(double[], double);
-    method public static int binarySearch(double[], int, int, double);
-    method public static int binarySearch(float[], float);
-    method public static int binarySearch(float[], int, int, float);
-    method public static int binarySearch(Object[], @NonNull Object);
-    method public static int binarySearch(Object[], int, int, @NonNull Object);
-    method public static <T> int binarySearch(T[], T, @Nullable java.util.Comparator<? super T>);
-    method public static <T> int binarySearch(T[], int, int, T, @Nullable java.util.Comparator<? super T>);
-    method public static <T> T[] copyOf(T[], int);
-    method public static <T, U> T[] copyOf(U[], int, @NonNull Class<? extends T[]>);
-    method public static byte[] copyOf(byte[], int);
-    method public static short[] copyOf(short[], int);
-    method public static int[] copyOf(int[], int);
-    method public static long[] copyOf(long[], int);
-    method public static char[] copyOf(char[], int);
-    method public static float[] copyOf(float[], int);
-    method public static double[] copyOf(double[], int);
-    method public static boolean[] copyOf(boolean[], int);
-    method public static <T> T[] copyOfRange(T[], int, int);
-    method public static <T, U> T[] copyOfRange(U[], int, int, @NonNull Class<? extends T[]>);
-    method public static byte[] copyOfRange(byte[], int, int);
-    method public static short[] copyOfRange(short[], int, int);
-    method public static int[] copyOfRange(int[], int, int);
-    method public static long[] copyOfRange(long[], int, int);
-    method public static char[] copyOfRange(char[], int, int);
-    method public static float[] copyOfRange(float[], int, int);
-    method public static double[] copyOfRange(double[], int, int);
-    method public static boolean[] copyOfRange(boolean[], int, int);
-    method public static boolean deepEquals(Object[], Object[]);
-    method public static int deepHashCode(Object[]);
-    method @NonNull public static String deepToString(Object[]);
-    method public static boolean equals(long[], long[]);
-    method public static boolean equals(int[], int[]);
-    method public static boolean equals(short[], short[]);
-    method public static boolean equals(char[], char[]);
-    method public static boolean equals(byte[], byte[]);
-    method public static boolean equals(boolean[], boolean[]);
-    method public static boolean equals(double[], double[]);
-    method public static boolean equals(float[], float[]);
-    method public static boolean equals(Object[], Object[]);
-    method public static void fill(long[], long);
-    method public static void fill(long[], int, int, long);
-    method public static void fill(int[], int);
-    method public static void fill(int[], int, int, int);
-    method public static void fill(short[], short);
-    method public static void fill(short[], int, int, short);
-    method public static void fill(char[], char);
-    method public static void fill(char[], int, int, char);
-    method public static void fill(byte[], byte);
-    method public static void fill(byte[], int, int, byte);
-    method public static void fill(boolean[], boolean);
-    method public static void fill(boolean[], int, int, boolean);
-    method public static void fill(double[], double);
-    method public static void fill(double[], int, int, double);
-    method public static void fill(float[], float);
-    method public static void fill(float[], int, int, float);
-    method public static void fill(Object[], @Nullable Object);
-    method public static void fill(Object[], int, int, @Nullable Object);
-    method public static int hashCode(long[]);
-    method public static int hashCode(int[]);
-    method public static int hashCode(short[]);
-    method public static int hashCode(char[]);
-    method public static int hashCode(byte[]);
-    method public static int hashCode(boolean[]);
-    method public static int hashCode(float[]);
-    method public static int hashCode(double[]);
-    method public static int hashCode(Object[]);
-    method public static <T> void parallelPrefix(T[], @NonNull java.util.function.BinaryOperator<T>);
-    method public static <T> void parallelPrefix(T[], int, int, @NonNull java.util.function.BinaryOperator<T>);
-    method public static void parallelPrefix(long[], @NonNull java.util.function.LongBinaryOperator);
-    method public static void parallelPrefix(long[], int, int, @NonNull java.util.function.LongBinaryOperator);
-    method public static void parallelPrefix(double[], @NonNull java.util.function.DoubleBinaryOperator);
-    method public static void parallelPrefix(double[], int, int, @NonNull java.util.function.DoubleBinaryOperator);
-    method public static void parallelPrefix(int[], @NonNull java.util.function.IntBinaryOperator);
-    method public static void parallelPrefix(int[], int, int, @NonNull java.util.function.IntBinaryOperator);
-    method public static <T> void parallelSetAll(T[], @NonNull java.util.function.IntFunction<? extends T>);
-    method public static void parallelSetAll(int[], @NonNull java.util.function.IntUnaryOperator);
-    method public static void parallelSetAll(long[], @NonNull java.util.function.IntToLongFunction);
-    method public static void parallelSetAll(double[], @NonNull java.util.function.IntToDoubleFunction);
-    method public static void parallelSort(byte[]);
-    method public static void parallelSort(byte[], int, int);
-    method public static void parallelSort(char[]);
-    method public static void parallelSort(char[], int, int);
-    method public static void parallelSort(short[]);
-    method public static void parallelSort(short[], int, int);
-    method public static void parallelSort(int[]);
-    method public static void parallelSort(int[], int, int);
-    method public static void parallelSort(long[]);
-    method public static void parallelSort(long[], int, int);
-    method public static void parallelSort(float[]);
-    method public static void parallelSort(float[], int, int);
-    method public static void parallelSort(double[]);
-    method public static void parallelSort(double[], int, int);
-    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(T[]);
-    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(T[], int, int);
-    method public static <T> void parallelSort(T[], @Nullable java.util.Comparator<? super T>);
-    method public static <T> void parallelSort(T[], int, int, @Nullable java.util.Comparator<? super T>);
-    method public static <T> void setAll(T[], @NonNull java.util.function.IntFunction<? extends T>);
-    method public static void setAll(int[], @NonNull java.util.function.IntUnaryOperator);
-    method public static void setAll(long[], @NonNull java.util.function.IntToLongFunction);
-    method public static void setAll(double[], @NonNull java.util.function.IntToDoubleFunction);
-    method public static void sort(int[]);
-    method public static void sort(int[], int, int);
-    method public static void sort(long[]);
-    method public static void sort(long[], int, int);
-    method public static void sort(short[]);
-    method public static void sort(short[], int, int);
-    method public static void sort(char[]);
-    method public static void sort(char[], int, int);
-    method public static void sort(byte[]);
-    method public static void sort(byte[], int, int);
-    method public static void sort(float[]);
-    method public static void sort(float[], int, int);
-    method public static void sort(double[]);
-    method public static void sort(double[], int, int);
-    method public static void sort(Object[]);
-    method public static void sort(Object[], int, int);
-    method public static <T> void sort(T[], @Nullable java.util.Comparator<? super T>);
-    method public static <T> void sort(T[], int, int, @Nullable java.util.Comparator<? super T>);
-    method @NonNull public static <T> java.util.Spliterator<T> spliterator(T[]);
-    method @NonNull public static <T> java.util.Spliterator<T> spliterator(T[], int, int);
-    method @NonNull public static java.util.Spliterator.OfInt spliterator(int[]);
-    method @NonNull public static java.util.Spliterator.OfInt spliterator(int[], int, int);
-    method @NonNull public static java.util.Spliterator.OfLong spliterator(long[]);
-    method @NonNull public static java.util.Spliterator.OfLong spliterator(long[], int, int);
-    method @NonNull public static java.util.Spliterator.OfDouble spliterator(double[]);
-    method @NonNull public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
-    method @NonNull public static <T> java.util.stream.Stream<T> stream(T[]);
-    method @NonNull public static <T> java.util.stream.Stream<T> stream(T[], int, int);
-    method @NonNull public static java.util.stream.IntStream stream(int[]);
-    method @NonNull public static java.util.stream.IntStream stream(int[], int, int);
-    method @NonNull public static java.util.stream.LongStream stream(long[]);
-    method @NonNull public static java.util.stream.LongStream stream(long[], int, int);
-    method @NonNull public static java.util.stream.DoubleStream stream(double[]);
-    method @NonNull public static java.util.stream.DoubleStream stream(double[], int, int);
-    method @NonNull public static String toString(long[]);
-    method @NonNull public static String toString(int[]);
-    method @NonNull public static String toString(short[]);
-    method @NonNull public static String toString(char[]);
-    method @NonNull public static String toString(byte[]);
-    method @NonNull public static String toString(boolean[]);
-    method @NonNull public static String toString(float[]);
-    method @NonNull public static String toString(double[]);
-    method @NonNull public static String toString(Object[]);
+    method @NonNull @java.lang.SafeVarargs public static <T> java.util.List<T> asList(@NonNull T...);
+    method public static int binarySearch(@NonNull long[], long);
+    method public static int binarySearch(@NonNull long[], int, int, long);
+    method public static int binarySearch(@NonNull int[], int);
+    method public static int binarySearch(@NonNull int[], int, int, int);
+    method public static int binarySearch(@NonNull short[], short);
+    method public static int binarySearch(@NonNull short[], int, int, short);
+    method public static int binarySearch(@NonNull char[], char);
+    method public static int binarySearch(@NonNull char[], int, int, char);
+    method public static int binarySearch(@NonNull byte[], byte);
+    method public static int binarySearch(@NonNull byte[], int, int, byte);
+    method public static int binarySearch(@NonNull double[], double);
+    method public static int binarySearch(@NonNull double[], int, int, double);
+    method public static int binarySearch(@NonNull float[], float);
+    method public static int binarySearch(@NonNull float[], int, int, float);
+    method public static int binarySearch(@NonNull Object[], @NonNull Object);
+    method public static int binarySearch(@NonNull Object[], int, int, @NonNull Object);
+    method public static <T> int binarySearch(@NonNull T[], T, @Nullable java.util.Comparator<? super T>);
+    method public static <T> int binarySearch(@NonNull T[], int, int, T, @Nullable java.util.Comparator<? super T>);
+    method @NonNull public static <T> T[] copyOf(@NonNull T[], int);
+    method @NonNull public static <T, U> T[] copyOf(@NonNull U[], int, @NonNull Class<? extends T[]>);
+    method @NonNull public static byte[] copyOf(@NonNull byte[], int);
+    method @NonNull public static short[] copyOf(@NonNull short[], int);
+    method @NonNull public static int[] copyOf(@NonNull int[], int);
+    method @NonNull public static long[] copyOf(@NonNull long[], int);
+    method @NonNull public static char[] copyOf(@NonNull char[], int);
+    method @NonNull public static float[] copyOf(@NonNull float[], int);
+    method @NonNull public static double[] copyOf(@NonNull double[], int);
+    method @NonNull public static boolean[] copyOf(@NonNull boolean[], int);
+    method @NonNull public static <T> T[] copyOfRange(@NonNull T[], int, int);
+    method @NonNull public static <T, U> T[] copyOfRange(@NonNull U[], int, int, @NonNull Class<? extends T[]>);
+    method @NonNull public static byte[] copyOfRange(@NonNull byte[], int, int);
+    method @NonNull public static short[] copyOfRange(@NonNull short[], int, int);
+    method @NonNull public static int[] copyOfRange(@NonNull int[], int, int);
+    method @NonNull public static long[] copyOfRange(@NonNull long[], int, int);
+    method @NonNull public static char[] copyOfRange(@NonNull char[], int, int);
+    method @NonNull public static float[] copyOfRange(@NonNull float[], int, int);
+    method @NonNull public static double[] copyOfRange(@NonNull double[], int, int);
+    method @NonNull public static boolean[] copyOfRange(@NonNull boolean[], int, int);
+    method public static boolean deepEquals(@Nullable Object[], @Nullable Object[]);
+    method public static int deepHashCode(@Nullable Object[]);
+    method @NonNull public static String deepToString(@Nullable Object[]);
+    method public static boolean equals(@Nullable long[], @Nullable long[]);
+    method public static boolean equals(@Nullable int[], @Nullable int[]);
+    method public static boolean equals(@Nullable short[], @Nullable short[]);
+    method public static boolean equals(@Nullable char[], @Nullable char[]);
+    method public static boolean equals(@Nullable byte[], @Nullable byte[]);
+    method public static boolean equals(@Nullable boolean[], @Nullable boolean[]);
+    method public static boolean equals(@Nullable double[], @Nullable double[]);
+    method public static boolean equals(@Nullable float[], @Nullable float[]);
+    method public static boolean equals(@Nullable Object[], @Nullable Object[]);
+    method public static void fill(@NonNull long[], long);
+    method public static void fill(@NonNull long[], int, int, long);
+    method public static void fill(@NonNull int[], int);
+    method public static void fill(@NonNull int[], int, int, int);
+    method public static void fill(@NonNull short[], short);
+    method public static void fill(@NonNull short[], int, int, short);
+    method public static void fill(@NonNull char[], char);
+    method public static void fill(@NonNull char[], int, int, char);
+    method public static void fill(@NonNull byte[], byte);
+    method public static void fill(@NonNull byte[], int, int, byte);
+    method public static void fill(@NonNull boolean[], boolean);
+    method public static void fill(@NonNull boolean[], int, int, boolean);
+    method public static void fill(@NonNull double[], double);
+    method public static void fill(@NonNull double[], int, int, double);
+    method public static void fill(@NonNull float[], float);
+    method public static void fill(@NonNull float[], int, int, float);
+    method public static void fill(@NonNull Object[], @Nullable Object);
+    method public static void fill(@NonNull Object[], int, int, @Nullable Object);
+    method public static int hashCode(@Nullable long[]);
+    method public static int hashCode(@Nullable int[]);
+    method public static int hashCode(@Nullable short[]);
+    method public static int hashCode(@Nullable char[]);
+    method public static int hashCode(@Nullable byte[]);
+    method public static int hashCode(@Nullable boolean[]);
+    method public static int hashCode(@Nullable float[]);
+    method public static int hashCode(@Nullable double[]);
+    method public static int hashCode(@Nullable Object[]);
+    method public static <T> void parallelPrefix(@NonNull T[], @NonNull java.util.function.BinaryOperator<T>);
+    method public static <T> void parallelPrefix(@NonNull T[], int, int, @NonNull java.util.function.BinaryOperator<T>);
+    method public static void parallelPrefix(@NonNull long[], @NonNull java.util.function.LongBinaryOperator);
+    method public static void parallelPrefix(@NonNull long[], int, int, @NonNull java.util.function.LongBinaryOperator);
+    method public static void parallelPrefix(@NonNull double[], @NonNull java.util.function.DoubleBinaryOperator);
+    method public static void parallelPrefix(@NonNull double[], int, int, @NonNull java.util.function.DoubleBinaryOperator);
+    method public static void parallelPrefix(@NonNull int[], @NonNull java.util.function.IntBinaryOperator);
+    method public static void parallelPrefix(@NonNull int[], int, int, @NonNull java.util.function.IntBinaryOperator);
+    method public static <T> void parallelSetAll(@NonNull T[], @NonNull java.util.function.IntFunction<? extends T>);
+    method public static void parallelSetAll(@NonNull int[], @NonNull java.util.function.IntUnaryOperator);
+    method public static void parallelSetAll(@NonNull long[], @NonNull java.util.function.IntToLongFunction);
+    method public static void parallelSetAll(@NonNull double[], @NonNull java.util.function.IntToDoubleFunction);
+    method public static void parallelSort(@NonNull byte[]);
+    method public static void parallelSort(@NonNull byte[], int, int);
+    method public static void parallelSort(@NonNull char[]);
+    method public static void parallelSort(@NonNull char[], int, int);
+    method public static void parallelSort(@NonNull short[]);
+    method public static void parallelSort(@NonNull short[], int, int);
+    method public static void parallelSort(@NonNull int[]);
+    method public static void parallelSort(@NonNull int[], int, int);
+    method public static void parallelSort(@NonNull long[]);
+    method public static void parallelSort(@NonNull long[], int, int);
+    method public static void parallelSort(@NonNull float[]);
+    method public static void parallelSort(@NonNull float[], int, int);
+    method public static void parallelSort(@NonNull double[]);
+    method public static void parallelSort(@NonNull double[], int, int);
+    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(@NonNull T[]);
+    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(@NonNull T[], int, int);
+    method public static <T> void parallelSort(@NonNull T[], @Nullable java.util.Comparator<? super T>);
+    method public static <T> void parallelSort(@NonNull T[], int, int, @Nullable java.util.Comparator<? super T>);
+    method public static <T> void setAll(@NonNull T[], @NonNull java.util.function.IntFunction<? extends T>);
+    method public static void setAll(@NonNull int[], @NonNull java.util.function.IntUnaryOperator);
+    method public static void setAll(@NonNull long[], @NonNull java.util.function.IntToLongFunction);
+    method public static void setAll(@NonNull double[], @NonNull java.util.function.IntToDoubleFunction);
+    method public static void sort(@NonNull int[]);
+    method public static void sort(@NonNull int[], int, int);
+    method public static void sort(@NonNull long[]);
+    method public static void sort(@NonNull long[], int, int);
+    method public static void sort(@NonNull short[]);
+    method public static void sort(@NonNull short[], int, int);
+    method public static void sort(@NonNull char[]);
+    method public static void sort(@NonNull char[], int, int);
+    method public static void sort(@NonNull byte[]);
+    method public static void sort(@NonNull byte[], int, int);
+    method public static void sort(@NonNull float[]);
+    method public static void sort(@NonNull float[], int, int);
+    method public static void sort(@NonNull double[]);
+    method public static void sort(@NonNull double[], int, int);
+    method public static void sort(@NonNull Object[]);
+    method public static void sort(@NonNull Object[], int, int);
+    method public static <T> void sort(@NonNull T[], @Nullable java.util.Comparator<? super T>);
+    method public static <T> void sort(@NonNull T[], int, int, @Nullable java.util.Comparator<? super T>);
+    method @NonNull public static <T> java.util.Spliterator<T> spliterator(@NonNull T[]);
+    method @NonNull public static <T> java.util.Spliterator<T> spliterator(@NonNull T[], int, int);
+    method @NonNull public static java.util.Spliterator.OfInt spliterator(@NonNull int[]);
+    method @NonNull public static java.util.Spliterator.OfInt spliterator(@NonNull int[], int, int);
+    method @NonNull public static java.util.Spliterator.OfLong spliterator(@NonNull long[]);
+    method @NonNull public static java.util.Spliterator.OfLong spliterator(@NonNull long[], int, int);
+    method @NonNull public static java.util.Spliterator.OfDouble spliterator(@NonNull double[]);
+    method @NonNull public static java.util.Spliterator.OfDouble spliterator(@NonNull double[], int, int);
+    method @NonNull public static <T> java.util.stream.Stream<T> stream(@NonNull T[]);
+    method @NonNull public static <T> java.util.stream.Stream<T> stream(@NonNull T[], int, int);
+    method @NonNull public static java.util.stream.IntStream stream(@NonNull int[]);
+    method @NonNull public static java.util.stream.IntStream stream(@NonNull int[], int, int);
+    method @NonNull public static java.util.stream.LongStream stream(@NonNull long[]);
+    method @NonNull public static java.util.stream.LongStream stream(@NonNull long[], int, int);
+    method @NonNull public static java.util.stream.DoubleStream stream(@NonNull double[]);
+    method @NonNull public static java.util.stream.DoubleStream stream(@NonNull double[], int, int);
+    method @NonNull public static String toString(@Nullable long[]);
+    method @NonNull public static String toString(@Nullable int[]);
+    method @NonNull public static String toString(@Nullable short[]);
+    method @NonNull public static String toString(@Nullable char[]);
+    method @NonNull public static String toString(@Nullable byte[]);
+    method @NonNull public static String toString(@Nullable boolean[]);
+    method @NonNull public static String toString(@Nullable float[]);
+    method @NonNull public static String toString(@Nullable double[]);
+    method @NonNull public static String toString(@Nullable Object[]);
   }
 
   public class Base64 {
@@ -66656,7 +66664,7 @@
     method public int getActualMaximum(int);
     method public int getActualMinimum(int);
     method @NonNull public static java.util.Set<java.lang.String> getAvailableCalendarTypes();
-    method public static java.util.Locale[] getAvailableLocales();
+    method @NonNull public static java.util.Locale[] getAvailableLocales();
     method @NonNull public String getCalendarType();
     method @Nullable public String getDisplayName(int, int, @NonNull java.util.Locale);
     method @Nullable public java.util.Map<java.lang.String,java.lang.Integer> getDisplayNames(int, int, @NonNull java.util.Locale);
@@ -66744,8 +66752,8 @@
     field public static final int YEAR = 1; // 0x1
     field public static final int ZONE_OFFSET = 15; // 0xf
     field protected boolean areFieldsSet;
-    field protected int[] fields;
-    field protected boolean[] isSet;
+    field @NonNull protected int[] fields;
+    field @NonNull protected boolean[] isSet;
     field protected boolean isTimeSet;
     field protected long time;
   }
@@ -66756,7 +66764,7 @@
     method @NonNull public java.util.Calendar.Builder set(int, int);
     method @NonNull public java.util.Calendar.Builder setCalendarType(@NonNull String);
     method @NonNull public java.util.Calendar.Builder setDate(int, int, int);
-    method @NonNull public java.util.Calendar.Builder setFields(int...);
+    method @NonNull public java.util.Calendar.Builder setFields(@NonNull int...);
     method @NonNull public java.util.Calendar.Builder setInstant(long);
     method @NonNull public java.util.Calendar.Builder setInstant(@NonNull java.util.Date);
     method @NonNull public java.util.Calendar.Builder setLenient(boolean);
@@ -66786,12 +66794,12 @@
     method public int size();
     method @NonNull public default java.util.Spliterator<E> spliterator();
     method @NonNull public default java.util.stream.Stream<E> stream();
-    method public Object[] toArray();
-    method public <T> T[] toArray(T[]);
+    method @NonNull public Object[] toArray();
+    method @NonNull public <T> T[] toArray(@NonNull T[]);
   }
 
   public class Collections {
-    method @java.lang.SafeVarargs public static <T> boolean addAll(@NonNull java.util.Collection<? super T>, T...);
+    method @java.lang.SafeVarargs public static <T> boolean addAll(@NonNull java.util.Collection<? super T>, @NonNull T...);
     method @NonNull public static <T> java.util.Queue<T> asLifoQueue(@NonNull java.util.Deque<T>);
     method public static <T> int binarySearch(@NonNull java.util.List<? extends java.lang.Comparable<? super T>>, @NonNull T);
     method public static <T> int binarySearch(@NonNull java.util.List<? extends T>, T, @Nullable java.util.Comparator<? super T>);
@@ -67309,7 +67317,7 @@
     method @NonNull public static java.util.List<java.lang.String> filterTags(@NonNull java.util.List<java.util.Locale.LanguageRange>, @NonNull java.util.Collection<java.lang.String>, @NonNull java.util.Locale.FilteringMode);
     method @NonNull public static java.util.List<java.lang.String> filterTags(@NonNull java.util.List<java.util.Locale.LanguageRange>, @NonNull java.util.Collection<java.lang.String>);
     method @NonNull public static java.util.Locale forLanguageTag(@NonNull String);
-    method public static java.util.Locale[] getAvailableLocales();
+    method @NonNull public static java.util.Locale[] getAvailableLocales();
     method @NonNull public String getCountry();
     method @NonNull public static java.util.Locale getDefault();
     method @NonNull public static java.util.Locale getDefault(@NonNull java.util.Locale.Category);
@@ -67327,8 +67335,8 @@
     method @NonNull public java.util.Set<java.lang.Character> getExtensionKeys();
     method @NonNull public String getISO3Country() throws java.util.MissingResourceException;
     method @NonNull public String getISO3Language() throws java.util.MissingResourceException;
-    method public static String[] getISOCountries();
-    method public static String[] getISOLanguages();
+    method @NonNull public static String[] getISOCountries();
+    method @NonNull public static String[] getISOLanguages();
     method @NonNull public String getLanguage();
     method @NonNull public String getScript();
     method @NonNull public java.util.Set<java.lang.String> getUnicodeLocaleAttributes();
@@ -67522,7 +67530,7 @@
     method public static <T> int compare(T, T, @NonNull java.util.Comparator<? super T>);
     method public static boolean deepEquals(@Nullable Object, @Nullable Object);
     method public static boolean equals(@Nullable Object, @Nullable Object);
-    method public static int hash(java.lang.Object...);
+    method public static int hash(@Nullable java.lang.Object...);
     method public static int hashCode(@Nullable Object);
     method public static boolean isNull(@Nullable Object);
     method public static boolean nonNull(@Nullable Object);
@@ -68187,7 +68195,7 @@
     method public void addElement(E);
     method public int capacity();
     method @NonNull public Object clone();
-    method public void copyInto(Object[]);
+    method public void copyInto(@NonNull Object[]);
     method public E elementAt(int);
     method @NonNull public java.util.Enumeration<E> elements();
     method public void ensureCapacity(int);
@@ -68207,7 +68215,7 @@
     method public void trimToSize();
     field protected int capacityIncrement;
     field protected int elementCount;
-    field protected Object[] elementData;
+    field @NonNull protected Object[] elementData;
   }
 
   public class WeakHashMap<K, V> extends java.util.AbstractMap<K,V> implements java.util.Map<K,V> {
@@ -68598,7 +68606,7 @@
   public class CopyOnWriteArrayList<E> implements java.lang.Cloneable java.util.List<E> java.util.RandomAccess java.io.Serializable {
     ctor public CopyOnWriteArrayList();
     ctor public CopyOnWriteArrayList(@NonNull java.util.Collection<? extends E>);
-    ctor public CopyOnWriteArrayList(E[]);
+    ctor public CopyOnWriteArrayList(@NonNull E[]);
     method public boolean add(E);
     method public void add(int, E);
     method public boolean addAll(@NonNull java.util.Collection<? extends E>);
@@ -68626,8 +68634,8 @@
     method public E set(int, E);
     method public int size();
     method @NonNull public java.util.List<E> subList(int, int);
-    method public Object[] toArray();
-    method public <T> T[] toArray(T[]);
+    method @NonNull public Object[] toArray();
+    method @NonNull public <T> T[] toArray(@NonNull T[]);
   }
 
   public class CopyOnWriteArraySet<E> extends java.util.AbstractSet<E> implements java.io.Serializable {
@@ -70379,7 +70387,7 @@
     method public void config(@NonNull java.util.function.Supplier<java.lang.String>);
     method public void entering(@Nullable String, @Nullable String);
     method public void entering(@Nullable String, @Nullable String, @Nullable Object);
-    method public void entering(@Nullable String, @Nullable String, Object[]);
+    method public void entering(@Nullable String, @Nullable String, @Nullable Object[]);
     method public void exiting(@Nullable String, @Nullable String);
     method public void exiting(@Nullable String, @Nullable String, @Nullable Object);
     method public void fine(@Nullable String);
@@ -70392,7 +70400,7 @@
     method @NonNull public static java.util.logging.Logger getAnonymousLogger(@Nullable String);
     method @Nullable public java.util.logging.Filter getFilter();
     method @NonNull public static final java.util.logging.Logger getGlobal();
-    method public java.util.logging.Handler[] getHandlers();
+    method @NonNull public java.util.logging.Handler[] getHandlers();
     method @Nullable public java.util.logging.Level getLevel();
     method @NonNull public static java.util.logging.Logger getLogger(@NonNull String);
     method @NonNull public static java.util.logging.Logger getLogger(@NonNull String, @Nullable String);
@@ -70408,7 +70416,7 @@
     method public void log(@NonNull java.util.logging.Level, @Nullable String);
     method public void log(@NonNull java.util.logging.Level, @NonNull java.util.function.Supplier<java.lang.String>);
     method public void log(@NonNull java.util.logging.Level, @Nullable String, @Nullable Object);
-    method public void log(@NonNull java.util.logging.Level, @Nullable String, Object[]);
+    method public void log(@NonNull java.util.logging.Level, @Nullable String, @Nullable Object[]);
     method public void log(@NonNull java.util.logging.Level, @Nullable String, @Nullable Throwable);
     method public void log(@NonNull java.util.logging.Level, @Nullable Throwable, @NonNull java.util.function.Supplier<java.lang.String>);
     method public void logp(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String);
@@ -70419,8 +70427,8 @@
     method public void logp(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable Throwable, @NonNull java.util.function.Supplier<java.lang.String>);
     method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String);
     method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String, @Nullable Object);
-    method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String, Object[]);
-    method public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable java.util.ResourceBundle, @Nullable String, java.lang.Object...);
+    method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String, @Nullable Object[]);
+    method public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable java.util.ResourceBundle, @Nullable String, @Nullable java.lang.Object...);
     method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String, @Nullable Throwable);
     method public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable java.util.ResourceBundle, @Nullable String, @Nullable Throwable);
     method public void removeHandler(@Nullable java.util.logging.Handler) throws java.lang.SecurityException;
@@ -70682,8 +70690,8 @@
     method public static boolean matches(@NonNull String, @NonNull CharSequence);
     method @NonNull public String pattern();
     method @NonNull public static String quote(@NonNull String);
-    method public String[] split(@NonNull CharSequence, int);
-    method public String[] split(@NonNull CharSequence);
+    method @NonNull public String[] split(@NonNull CharSequence, int);
+    method @NonNull public String[] split(@NonNull CharSequence);
     method @NonNull public java.util.stream.Stream<java.lang.String> splitAsStream(@NonNull CharSequence);
     field public static final int CANON_EQ = 128; // 0x80
     field public static final int CASE_INSENSITIVE = 2; // 0x2
diff --git a/api/system-current.txt b/api/system-current.txt
index 97094c7..8046006 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -101,6 +101,7 @@
     field public static final String OBSERVE_APP_USAGE = "android.permission.OBSERVE_APP_USAGE";
     field public static final String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG";
     field public static final String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
+    field public static final String PACKET_KEEPALIVE_OFFLOAD = "android.permission.PACKET_KEEPALIVE_OFFLOAD";
     field public static final String PEERS_MAC_ADDRESS = "android.permission.PEERS_MAC_ADDRESS";
     field public static final String PERFORM_CDMA_PROVISIONING = "android.permission.PERFORM_CDMA_PROVISIONING";
     field public static final String PERFORM_SIM_ACTIVATION = "android.permission.PERFORM_SIM_ACTIVATION";
@@ -837,6 +838,7 @@
     method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public void startActivityAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle);
     field public static final String BACKUP_SERVICE = "backup";
     field public static final String CONTEXTHUB_SERVICE = "contexthub";
+    field public static final String DYNAMIC_ANDROID_SERVICE = "dynamic_android";
     field public static final String EUICC_CARD_SERVICE = "euicc_card";
     field public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
     field public static final String NETD_SERVICE = "netd";
@@ -3058,6 +3060,7 @@
 
   public class CaptivePortal implements android.os.Parcelable {
     ctor public CaptivePortal(android.os.IBinder);
+    method public void logEvent(int, String);
     method public void useNetwork();
     field public static final int APP_RETURN_DISMISSED = 0; // 0x0
     field public static final int APP_RETURN_UNWANTED = 1; // 0x1
@@ -3065,9 +3068,10 @@
   }
 
   public class ConnectivityManager {
-    method @RequiresPermission("android.permission.PACKET_KEEPALIVE_OFFLOAD") public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull java.io.FileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
+    method @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull java.io.FileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
     method public boolean getAvoidBadWifi();
     method @RequiresPermission(android.Manifest.permission.LOCAL_MAC_ADDRESS) public String getCaptivePortalServerUrl();
+    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementValue(int, boolean, @NonNull android.net.ConnectivityManager.TetheringEntitlementValueListener, @Nullable android.os.Handler);
     method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void setAirplaneMode(boolean);
     method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
@@ -3078,6 +3082,9 @@
     field public static final int TETHERING_BLUETOOTH = 2; // 0x2
     field public static final int TETHERING_USB = 1; // 0x1
     field public static final int TETHERING_WIFI = 0; // 0x0
+    field public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; // 0xd
+    field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
+    field public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
   }
 
   public abstract static class ConnectivityManager.OnStartTetheringCallback {
@@ -3086,6 +3093,11 @@
     method public void onTetheringStarted();
   }
 
+  public abstract static class ConnectivityManager.TetheringEntitlementValueListener {
+    ctor public ConnectivityManager.TetheringEntitlementValueListener();
+    method public void onEntitlementResult(int);
+  }
+
   public final class IpPrefix implements android.os.Parcelable {
     ctor public IpPrefix(java.net.InetAddress, int);
     ctor public IpPrefix(String);
@@ -3185,6 +3197,10 @@
     field public static final String EXTRA_PACKAGE_NAME = "packageName";
   }
 
+  public class NetworkStack {
+    field public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK";
+  }
+
   public final class RouteInfo implements android.os.Parcelable {
     ctor public RouteInfo(android.net.IpPrefix, java.net.InetAddress, String, int);
     method public int getType();
@@ -4303,6 +4319,7 @@
   }
 
   public final class UserHandle implements android.os.Parcelable {
+    method public static int getAppId(int);
     method public int getIdentifier();
     method @Deprecated public boolean isOwner();
     method public boolean isSystem();
@@ -6049,6 +6066,7 @@
   public class PhoneStateListener {
     method public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes);
     method public void onCallDisconnectCauseChanged(int, int);
+    method public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
     method public void onPreciseCallStateChanged(android.telephony.PreciseCallState);
     method public void onPreciseDataConnectionStateChanged(android.telephony.PreciseDataConnectionState);
     method public void onRadioPowerStateChanged(int);
@@ -6056,6 +6074,7 @@
     method public void onVoiceActivationStateChanged(int);
     field public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
     field public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
+    field public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
     field public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
     field public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
     field public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
@@ -6301,7 +6320,6 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
-    method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public int getPreferredNetworkType(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
     method public int getSimApplicationState();
     method public int getSimCardState();
@@ -6316,6 +6334,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCurrentPotentialEmergencyNumber(@NonNull String);
     method public boolean isDataConnectivityPossible();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMultisimCarrierRestricted();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
@@ -6332,6 +6351,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultisimCarrierRestriction(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int);
@@ -6356,29 +6376,6 @@
     field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
     field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
     field public static final long MAX_NUMBER_VERIFICATION_TIMEOUT_MILLIS = 60000L; // 0xea60L
-    field public static final int NETWORK_MODE_CDMA_EVDO = 4; // 0x4
-    field public static final int NETWORK_MODE_CDMA_NO_EVDO = 5; // 0x5
-    field public static final int NETWORK_MODE_EVDO_NO_CDMA = 6; // 0x6
-    field public static final int NETWORK_MODE_GLOBAL = 7; // 0x7
-    field public static final int NETWORK_MODE_GSM_ONLY = 1; // 0x1
-    field public static final int NETWORK_MODE_GSM_UMTS = 3; // 0x3
-    field public static final int NETWORK_MODE_LTE_CDMA_EVDO = 8; // 0x8
-    field public static final int NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA = 10; // 0xa
-    field public static final int NETWORK_MODE_LTE_GSM_WCDMA = 9; // 0x9
-    field public static final int NETWORK_MODE_LTE_ONLY = 11; // 0xb
-    field public static final int NETWORK_MODE_LTE_TDSCDMA = 15; // 0xf
-    field public static final int NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 22; // 0x16
-    field public static final int NETWORK_MODE_LTE_TDSCDMA_GSM = 17; // 0x11
-    field public static final int NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA = 20; // 0x14
-    field public static final int NETWORK_MODE_LTE_TDSCDMA_WCDMA = 19; // 0x13
-    field public static final int NETWORK_MODE_LTE_WCDMA = 12; // 0xc
-    field public static final int NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 21; // 0x15
-    field public static final int NETWORK_MODE_TDSCDMA_GSM = 16; // 0x10
-    field public static final int NETWORK_MODE_TDSCDMA_GSM_WCDMA = 18; // 0x12
-    field public static final int NETWORK_MODE_TDSCDMA_ONLY = 13; // 0xd
-    field public static final int NETWORK_MODE_TDSCDMA_WCDMA = 14; // 0xe
-    field public static final int NETWORK_MODE_WCDMA_ONLY = 2; // 0x2
-    field public static final int NETWORK_MODE_WCDMA_PREF = 0; // 0x0
     field public static final int NETWORK_TYPE_BITMASK_1xRTT = 128; // 0x80
     field public static final int NETWORK_TYPE_BITMASK_CDMA = 16; // 0x10
     field public static final int NETWORK_TYPE_BITMASK_EDGE = 4; // 0x4
@@ -6839,6 +6836,16 @@
     field public final java.util.HashMap<java.lang.String,android.os.Bundle> mParticipants;
   }
 
+  public class ImsException extends java.lang.Exception {
+    ctor public ImsException(@Nullable String);
+    ctor public ImsException(@Nullable String, int);
+    ctor public ImsException(@Nullable String, int, Throwable);
+    method public int getCode();
+    field public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; // 0x1
+    field public static final int CODE_ERROR_UNSPECIFIED = 0; // 0x0
+    field public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; // 0x2
+  }
+
   public final class ImsExternalCallState implements android.os.Parcelable {
     ctor public ImsExternalCallState(String, android.net.Uri, android.net.Uri, boolean, int, int, boolean);
     method public int describeContents();
@@ -6856,7 +6863,7 @@
   }
 
   public class ImsMmTelManager {
-    method public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(android.content.Context, int);
+    method public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiModeSetting();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAdvancedCallingSettingEnabled();
@@ -6865,8 +6872,8 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiRoamingSettingEnabled();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiSettingEnabled();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVtSettingEnabled();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSetting(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int);
@@ -7301,11 +7308,11 @@
   }
 
   public class ProvisioningManager {
-    method public static android.telephony.ims.ProvisioningManager createForSubscriptionId(android.content.Context, int);
+    method public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
     method @WorkerThread @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getProvisioningIntValue(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
     method @WorkerThread @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getProvisioningStringValue(int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, String);
diff --git a/api/test-current.txt b/api/test-current.txt
index 3ae5e5d..34c8f6e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -600,6 +600,7 @@
 
   public class CaptivePortal implements android.os.Parcelable {
     ctor public CaptivePortal(android.os.IBinder);
+    method public void logEvent(int, String);
     method public void useNetwork();
     field public static final int APP_RETURN_DISMISSED = 0; // 0x0
     field public static final int APP_RETURN_UNWANTED = 1; // 0x1
@@ -668,6 +669,10 @@
     method public boolean satisfiedByNetworkCapabilities(android.net.NetworkCapabilities);
   }
 
+  public class NetworkStack {
+    field public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK";
+  }
+
   public final class RouteInfo implements android.os.Parcelable {
     ctor public RouteInfo(android.net.IpPrefix, java.net.InetAddress, String, int);
     method public int getType();
@@ -1789,6 +1794,10 @@
     method public boolean isSystemGroup();
   }
 
+  public abstract class LayoutInflater {
+    method public void setPrecompiledLayoutsEnabledForTesting(boolean);
+  }
+
   public final class MotionEvent extends android.view.InputEvent implements android.os.Parcelable {
     method public void setActionButton(int);
     method public void setButtonState(int);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index b2951df..a8fc9d24 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -114,11 +114,13 @@
 import android.os.Build;
 import android.os.DeviceIdleManager;
 import android.os.DropBoxManager;
+import android.os.DynamicAndroidManager;
 import android.os.HardwarePropertiesManager;
 import android.os.IBatteryPropertiesRegistrar;
 import android.os.IBinder;
 import android.os.IDeviceIdleController;
 import android.os.IDumpstate;
+import android.os.IDynamicAndroidService;
 import android.os.IHardwarePropertiesManager;
 import android.os.IPowerManager;
 import android.os.IRecoverySystem;
@@ -1065,6 +1067,16 @@
                             throws ServiceNotFoundException {
                         return new TimeZoneDetector();
                     }});
+        registerService(Context.DYNAMIC_ANDROID_SERVICE, DynamicAndroidManager.class,
+                new CachedServiceFetcher<DynamicAndroidManager>() {
+                    @Override
+                    public DynamicAndroidManager createService(ContextImpl ctx)
+                            throws ServiceNotFoundException {
+                        IBinder b = ServiceManager.getServiceOrThrow(
+                                Context.DYNAMIC_ANDROID_SERVICE);
+                        return new DynamicAndroidManager(
+                                IDynamicAndroidService.Stub.asInterface(b));
+                    }});
     }
 
     /**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 8959540..ba6e7ae8 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4304,6 +4304,14 @@
      */
     public static final String TELEPHONY_RCS_SERVICE = "ircs";
 
+     /**
+     * Use with {@link #getSystemService(String)} to retrieve an
+     * {@link android.os.DynamicAndroidManager}.
+     * @hide
+     */
+    @SystemApi
+    public static final String DYNAMIC_ANDROID_SERVICE = "dynamic_android";
+
     /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 2130c39..92c757c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5501,7 +5501,7 @@
      * @param newState The new enabled state for the component.
      * @param flags Optional behavior flags.
      */
-    public abstract void setComponentEnabledSetting(ComponentName componentName,
+    public abstract void setComponentEnabledSetting(@NonNull ComponentName componentName,
             @EnabledState int newState, @EnabledFlags int flags);
 
     /**
@@ -5515,7 +5515,7 @@
      * @return Returns the current enabled state for the component.
      */
     public abstract @EnabledState int getComponentEnabledSetting(
-            ComponentName componentName);
+            @NonNull ComponentName componentName);
 
     /**
      * Set the enabled setting for an application
@@ -5528,7 +5528,7 @@
      * @param newState The new enabled state for the application.
      * @param flags Optional behavior flags.
      */
-    public abstract void setApplicationEnabledSetting(String packageName,
+    public abstract void setApplicationEnabledSetting(@NonNull String packageName,
             @EnabledState int newState, @EnabledFlags int flags);
 
     /**
@@ -5542,7 +5542,7 @@
      * @return Returns the current enabled state for the application.
      * @throws IllegalArgumentException if the named package does not exist.
      */
-    public abstract @EnabledState int getApplicationEnabledSetting(String packageName);
+    public abstract @EnabledState int getApplicationEnabledSetting(@NonNull String packageName);
 
     /**
      * Flush the package restrictions for a given user to disk. This forces the package restrictions
diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java
index 3b01266..3ab35e1 100644
--- a/core/java/android/net/CaptivePortal.java
+++ b/core/java/android/net/CaptivePortal.java
@@ -117,4 +117,17 @@
         } catch (RemoteException e) {
         }
     }
+
+    /**
+     * Log a captive portal login event.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public void logEvent(int eventId, String packageName) {
+        try {
+            ICaptivePortal.Stub.asInterface(mBinder).logEvent(eventId, packageName);
+        } catch (RemoteException e) {
+        }
+    }
 }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3bae12e..1240ef8 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1033,34 +1033,6 @@
         }
     }
 
-    /**
-     * Configures an always-on VPN connection through a specific application.
-     * This connection is automatically granted and persisted after a reboot.
-     *
-     * <p>The designated package should declare a {@link VpnService} in its
-     *    manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE},
-     *    otherwise the call will fail.
-     *
-     * @param userId The identifier of the user to set an always-on VPN for.
-     * @param vpnPackage The package name for an installed VPN app on the device, or {@code null}
-     *                   to remove an existing always-on VPN configuration.
-     * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
-     *        {@code false} otherwise.
-     * @return {@code true} if the package is set as always-on VPN controller;
-     *         {@code false} otherwise.
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
-    public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage,
-            boolean lockdownEnabled) {
-        try {
-            return mService.setAlwaysOnVpnPackage(
-                    userId, vpnPackage, lockdownEnabled, /* whitelist */ null);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
    /**
      * Returns the package name of the currently set always-on VPN application.
      * If there is no always-on VPN set, or the VPN is provided by the system instead
@@ -2609,6 +2581,7 @@
     }
 
     /** {@hide} */
+    @SystemApi
     public static final int TETHER_ERROR_NO_ERROR           = 0;
     /** {@hide} */
     public static final int TETHER_ERROR_UNKNOWN_IFACE      = 1;
@@ -2631,9 +2604,13 @@
     /** {@hide} */
     public static final int TETHER_ERROR_IFACE_CFG_ERROR      = 10;
     /** {@hide} */
+    @SystemApi
     public static final int TETHER_ERROR_PROVISION_FAILED     = 11;
     /** {@hide} */
     public static final int TETHER_ERROR_DHCPSERVER_ERROR     = 12;
+    /** {@hide} */
+    @SystemApi
+    public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN  = 13;
 
     /**
      * Get a more detailed error code after a Tethering or Untethering
@@ -2656,6 +2633,65 @@
     }
 
     /**
+     * Callback for use with {@link #getLatestTetheringEntitlementValue} to find out whether
+     * entitlement succeeded.
+     * @hide
+     */
+    @SystemApi
+    public abstract static class TetheringEntitlementValueListener  {
+        /**
+         * Called to notify entitlement result.
+         *
+         * @param resultCode a int value of entitlement result. It may be one of
+         *         {@link #TETHER_ERROR_NO_ERROR},
+         *         {@link #TETHER_ERROR_PROVISION_FAILED}, or
+         *         {@link #TETHER_ERROR_ENTITLEMENT_UNKONWN}.
+         */
+        public void onEntitlementResult(int resultCode) {}
+    }
+
+    /**
+     * Get the last value of the entitlement check on this downstream. If the cached value is
+     * {@link #TETHER_ERROR_NO_ERROR} or showEntitlementUi argument is false, it just return the
+     * cached value. Otherwise, a UI-based entitlement check would be performed. It is not
+     * guaranteed that the UI-based entitlement check will complete in any specific time period
+     * and may in fact never complete. Any successful entitlement check the platform performs for
+     * any reason will update the cached value.
+     *
+     * @param type the downstream type of tethering. Must be one of
+     *         {@link #TETHERING_WIFI},
+     *         {@link #TETHERING_USB}, or
+     *         {@link #TETHERING_BLUETOOTH}.
+     * @param showEntitlementUi a boolean indicating whether to run UI-based entitlement check.
+     * @param listener an {@link TetheringEntitlementValueListener} which will be called to notify
+     *         the caller of the result of entitlement check. The listener may be called zero or
+     *         one time.
+     * @param handler {@link Handler} to specify the thread upon which the listener will be invoked.
+     * {@hide}
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+    public void getLatestTetheringEntitlementValue(int type, boolean showEntitlementUi,
+            @NonNull final TetheringEntitlementValueListener listener, @Nullable Handler handler) {
+        Preconditions.checkNotNull(listener, "TetheringEntitlementValueListener cannot be null.");
+        ResultReceiver wrappedListener = new ResultReceiver(handler) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                listener.onEntitlementResult(resultCode);
+            }
+        };
+
+        try {
+            String pkgName = mContext.getOpPackageName();
+            Log.i(TAG, "getLatestTetheringEntitlementValue:" + pkgName);
+            mService.getLatestTetheringEntitlementValue(type, wrappedListener,
+                    showEntitlementUi, pkgName);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Report network connectivity status.  This is currently used only
      * to alter status bar UI.
      * <p>This method requires the caller to hold the permission
@@ -3970,10 +4006,17 @@
     @Deprecated
     public static boolean setProcessDefaultNetwork(@Nullable Network network) {
         int netId = (network == null) ? NETID_UNSET : network.netId;
-        if (netId == NetworkUtils.getBoundNetworkForProcess()) {
-            return true;
+        boolean isSameNetId = (netId == NetworkUtils.getBoundNetworkForProcess());
+
+        if (netId != NETID_UNSET) {
+            netId = network.getNetIdForResolv();
         }
-        if (NetworkUtils.bindProcessToNetwork(netId)) {
+
+        if (!NetworkUtils.bindProcessToNetwork(netId)) {
+            return false;
+        }
+
+        if (!isSameNetId) {
             // Set HTTP proxy system properties to match network.
             // TODO: Deprecate this static method and replace it with a non-static version.
             try {
@@ -3987,10 +4030,9 @@
             // Must flush socket pool as idle sockets will be bound to previous network and may
             // cause subsequent fetches to be performed on old network.
             NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged();
-            return true;
-        } else {
-            return false;
         }
+
+        return true;
     }
 
     /**
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
index 6c291c2..6f9e65f 100644
--- a/core/java/android/net/DhcpResults.java
+++ b/core/java/android/net/DhcpResults.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.annotation.UnsupportedAppUsage;
+import android.net.shared.InetAddressUtils;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -73,19 +74,21 @@
     public StaticIpConfiguration toStaticIpConfiguration() {
         final StaticIpConfiguration s = new StaticIpConfiguration();
         // All these except dnsServers are immutable, so no need to make copies.
-        s.ipAddress = ipAddress;
-        s.gateway = gateway;
-        s.dnsServers.addAll(dnsServers);
-        s.domains = domains;
+        s.setIpAddress(ipAddress);
+        s.setGateway(gateway);
+        for (InetAddress addr : dnsServers) {
+            s.addDnsServer(addr);
+        }
+        s.setDomains(domains);
         return s;
     }
 
     public DhcpResults(StaticIpConfiguration source) {
         if (source != null) {
-            ipAddress = source.ipAddress;
-            gateway = source.gateway;
-            dnsServers.addAll(source.dnsServers);
-            domains = source.domains;
+            ipAddress = source.getIpAddress();
+            gateway = source.getGateway();
+            dnsServers.addAll(source.getDnsServers());
+            domains = source.getDomains();
         }
     }
 
@@ -177,7 +180,7 @@
         toStaticIpConfiguration().writeToParcel(dest, flags);
         dest.writeInt(leaseDuration);
         dest.writeInt(mtu);
-        NetworkUtils.parcelInetAddress(dest, serverAddress, flags);
+        InetAddressUtils.parcelInetAddress(dest, serverAddress, flags);
         dest.writeString(vendorInfo);
     }
 
@@ -191,7 +194,7 @@
         final DhcpResults dhcpResults = new DhcpResults(s);
         dhcpResults.leaseDuration = in.readInt();
         dhcpResults.mtu = in.readInt();
-        dhcpResults.serverAddress = (Inet4Address) NetworkUtils.unparcelInetAddress(in);
+        dhcpResults.serverAddress = (Inet4Address) InetAddressUtils.unparcelInetAddress(in);
         dhcpResults.vendorInfo = in.readString();
         return dhcpResults;
     }
@@ -200,7 +203,7 @@
     // Not part of the superclass because they're only used by the JNI iterface to the DHCP daemon.
     public boolean setIpAddress(String addrString, int prefixLength) {
         try {
-            Inet4Address addr = (Inet4Address) NetworkUtils.numericToInetAddress(addrString);
+            Inet4Address addr = (Inet4Address) InetAddresses.parseNumericAddress(addrString);
             ipAddress = new LinkAddress(addr, prefixLength);
         } catch (IllegalArgumentException|ClassCastException e) {
             Log.e(TAG, "setIpAddress failed with addrString " + addrString + "/" + prefixLength);
@@ -211,7 +214,7 @@
 
     public boolean setGateway(String addrString) {
         try {
-            gateway = NetworkUtils.numericToInetAddress(addrString);
+            gateway = InetAddresses.parseNumericAddress(addrString);
         } catch (IllegalArgumentException e) {
             Log.e(TAG, "setGateway failed with addrString " + addrString);
             return true;
@@ -222,7 +225,7 @@
     public boolean addDns(String addrString) {
         if (TextUtils.isEmpty(addrString) == false) {
             try {
-                dnsServers.add(NetworkUtils.numericToInetAddress(addrString));
+                dnsServers.add(InetAddresses.parseNumericAddress(addrString));
             } catch (IllegalArgumentException e) {
                 Log.e(TAG, "addDns failed with addrString " + addrString);
                 return true;
diff --git a/core/java/android/net/ICaptivePortal.aidl b/core/java/android/net/ICaptivePortal.aidl
index 56ae57d..707b4f6 100644
--- a/core/java/android/net/ICaptivePortal.aidl
+++ b/core/java/android/net/ICaptivePortal.aidl
@@ -22,4 +22,5 @@
  */
 oneway interface ICaptivePortal {
     void appResponse(int response);
+    void logEvent(int eventId, String packageName);
 }
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index fd7360f..78fafeb 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -197,4 +197,7 @@
     int getConnectionOwnerUid(in ConnectionInfo connectionInfo);
     boolean isCallerCurrentAlwaysOnVpnApp();
     boolean isCallerCurrentAlwaysOnVpnLockdownApp();
+
+    void getLatestTetheringEntitlementValue(int type, in ResultReceiver receiver,
+            boolean showEntitlementUi, String callerPkg);
 }
diff --git a/core/java/android/net/INetworkMonitorCallbacks.aidl b/core/java/android/net/INetworkMonitorCallbacks.aidl
index 0bc2575..a8682f9 100644
--- a/core/java/android/net/INetworkMonitorCallbacks.aidl
+++ b/core/java/android/net/INetworkMonitorCallbacks.aidl
@@ -26,4 +26,5 @@
     void notifyPrivateDnsConfigResolved(in PrivateDnsConfigParcel config);
     void showProvisioningNotification(String action);
     void hideProvisioningNotification();
+    void logCaptivePortalLoginEvent(int eventId, String packageName);
 }
\ No newline at end of file
diff --git a/core/java/android/net/INetworkStackConnector.aidl b/core/java/android/net/INetworkStackConnector.aidl
index 8b64f1c..e052488 100644
--- a/core/java/android/net/INetworkStackConnector.aidl
+++ b/core/java/android/net/INetworkStackConnector.aidl
@@ -16,6 +16,7 @@
 package android.net;
 
 import android.net.INetworkMonitorCallbacks;
+import android.net.NetworkParcelable;
 import android.net.dhcp.DhcpServingParamsParcel;
 import android.net.dhcp.IDhcpServerCallbacks;
 import android.net.ip.IIpClientCallbacks;
@@ -24,6 +25,7 @@
 oneway interface INetworkStackConnector {
     void makeDhcpServer(in String ifName, in DhcpServingParamsParcel params,
         in IDhcpServerCallbacks cb);
-    void makeNetworkMonitor(int netId, String name, in INetworkMonitorCallbacks cb);
+    void makeNetworkMonitor(in NetworkParcelable network, String name,
+        in INetworkMonitorCallbacks cb);
     void makeIpClient(in String ifName, in IIpClientCallbacks callbacks);
 }
\ No newline at end of file
diff --git a/core/java/android/net/NetworkStack.java b/core/java/android/net/NetworkStack.java
index d277034..b6cd635 100644
--- a/core/java/android/net/NetworkStack.java
+++ b/core/java/android/net/NetworkStack.java
@@ -20,7 +20,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -46,9 +48,22 @@
  * @hide
  */
 @SystemService(Context.NETWORK_STACK_SERVICE)
+@SystemApi
+@TestApi
 public class NetworkStack {
     private static final String TAG = NetworkStack.class.getSimpleName();
 
+    /**
+     * Permission granted only to the NetworkStack APK, defined in NetworkStackStub with signature
+     * protection level.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final String PERMISSION_MAINLINE_NETWORK_STACK =
+            "android.permission.MAINLINE_NETWORK_STACK";
+
+    /** @hide */
     public static final String NETWORKSTACK_PACKAGE_NAME = "com.android.mainline.networkstack";
 
     private static final int NETWORKSTACK_TIMEOUT_MS = 10_000;
@@ -66,12 +81,14 @@
         void onNetworkStackConnected(INetworkStackConnector connector);
     }
 
+    /** @hide */
     public NetworkStack() { }
 
     /**
      * Create a DHCP server according to the specified parameters.
      *
      * <p>The server will be returned asynchronously through the provided callbacks.
+     * @hide
      */
     public void makeDhcpServer(final String ifName, final DhcpServingParamsParcel params,
             final IDhcpServerCallbacks cb) {
@@ -88,6 +105,7 @@
      * Create an IpClient on the specified interface.
      *
      * <p>The IpClient will be returned asynchronously through the provided callbacks.
+     * @hide
      */
     public void makeIpClient(String ifName, IIpClientCallbacks cb) {
         requestConnector(connector -> {
@@ -103,11 +121,13 @@
      * Create a NetworkMonitor.
      *
      * <p>The INetworkMonitor will be returned asynchronously through the provided callbacks.
+     * @hide
      */
-    public void makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb) {
+    public void makeNetworkMonitor(
+            NetworkParcelable network, String name, INetworkMonitorCallbacks cb) {
         requestConnector(connector -> {
             try {
-                connector.makeNetworkMonitor(network.netId, name, cb);
+                connector.makeNetworkMonitor(network, name, cb);
             } catch (RemoteException e) {
                 e.rethrowFromSystemServer();
             }
@@ -152,6 +172,7 @@
      * the system server on devices that do not support the network stack module. The network stack
      * connector will then be delivered asynchronously to clients that requested it before it was
      * started.
+     * @hide
      */
     public void start(Context context) {
         mNetworkStackStartRequested = true;
@@ -222,7 +243,7 @@
     private void requestConnector(@NonNull NetworkStackCallback request) {
         // TODO: PID check.
         final int caller = Binder.getCallingUid();
-        if (caller != Process.SYSTEM_UID && caller != Process.BLUETOOTH_UID) {
+        if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) {
             // Don't even attempt to obtain the connector and give a nice error message
             throw new SecurityException(
                     "Only the system server should try to bind to the network stack.");
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 44170b5..07668a9 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -19,7 +19,6 @@
 import android.annotation.UnsupportedAppUsage;
 import android.net.shared.Inet4AddressUtils;
 import android.os.Build;
-import android.os.Parcel;
 import android.system.ErrnoException;
 import android.util.Log;
 import android.util.Pair;
@@ -247,32 +246,6 @@
     }
 
     /**
-     * Writes an InetAddress to a parcel. The address may be null. This is likely faster than
-     * calling writeSerializable.
-     */
-    protected static void parcelInetAddress(Parcel parcel, InetAddress address, int flags) {
-        byte[] addressArray = (address != null) ? address.getAddress() : null;
-        parcel.writeByteArray(addressArray);
-    }
-
-    /**
-     * Reads an InetAddress from a parcel. Returns null if the address that was written was null
-     * or if the data is invalid.
-     */
-    protected static InetAddress unparcelInetAddress(Parcel in) {
-        byte[] addressArray = in.createByteArray();
-        if (addressArray == null) {
-            return null;
-        }
-        try {
-            return InetAddress.getByAddress(addressArray);
-        } catch (UnknownHostException e) {
-            return null;
-        }
-    }
-
-
-    /**
      *  Masks a raw IP address byte array with the specified prefix length.
      */
     public static void maskRawAddress(byte[] array, int prefixLength) {
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index 25bae3c..99cf3a9 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -19,6 +19,7 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
+import android.net.shared.InetAddressUtils;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -232,10 +233,10 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeParcelable(ipAddress, flags);
-        NetworkUtils.parcelInetAddress(dest, gateway, flags);
+        InetAddressUtils.parcelInetAddress(dest, gateway, flags);
         dest.writeInt(dnsServers.size());
         for (InetAddress dnsServer : dnsServers) {
-            NetworkUtils.parcelInetAddress(dest, dnsServer, flags);
+            InetAddressUtils.parcelInetAddress(dest, dnsServer, flags);
         }
         dest.writeString(domains);
     }
@@ -244,11 +245,11 @@
     public static StaticIpConfiguration readFromParcel(Parcel in) {
         final StaticIpConfiguration s = new StaticIpConfiguration();
         s.ipAddress = in.readParcelable(null);
-        s.gateway = NetworkUtils.unparcelInetAddress(in);
+        s.gateway = InetAddressUtils.unparcelInetAddress(in);
         s.dnsServers.clear();
         int size = in.readInt();
         for (int i = 0; i < size; i++) {
-            s.dnsServers.add(NetworkUtils.unparcelInetAddress(in));
+            s.dnsServers.add(InetAddressUtils.unparcelInetAddress(in));
         }
         s.domains = in.readString();
         return s;
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index dc099a4..784f233 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -791,6 +791,27 @@
         }
 
         /**
+         * Marks the VPN network as metered. A VPN network is classified as metered when the user is
+         * sensitive to heavy data usage due to monetary costs and/or data limitations. In such
+         * cases, you should set this to {@code true} so that apps on the system can avoid doing
+         * large data transfers. Otherwise, set this to {@code false}. Doing so would cause VPN
+         * network to inherit its meteredness from its underlying networks.
+         *
+         * <p>VPN apps targeting {@link android.os.Build.VERSION_CODES#Q} or above will be
+         * considered metered by default.
+         *
+         * @param isMetered {@code true} if VPN network should be treated as metered regardless of
+         *     underlying network meteredness
+         * @return this {@link Builder} object to facilitate chaining method calls
+         * @see #setUnderlyingNetworks(Networks[])
+         * @see ConnectivityManager#isActiveNetworkMetered()
+         */
+        public Builder setMetered(boolean isMetered) {
+            mConfig.isMetered = isMetered;
+            return this;
+        }
+
+        /**
          * Create a VPN interface using the parameters supplied to this
          * builder. The interface works on IP packets, and a file descriptor
          * is returned for the application to access them. Each read
diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java
index 2a942ee..3008115 100644
--- a/core/java/android/net/metrics/DhcpClientEvent.java
+++ b/core/java/android/net/metrics/DhcpClientEvent.java
@@ -31,10 +31,6 @@
 public final class DhcpClientEvent implements IpConnectivityLog.Event {
 
     // Names for recording DhcpClient pseudo-state transitions.
-    /** {@hide} Represents transitions from DhcpInitState to DhcpBoundState */
-    public static final String INITIAL_BOUND = "InitialBoundState";
-    /** {@hide} Represents transitions from and to DhcpBoundState via DhcpRenewingState */
-    public static final String RENEWING_BOUND = "RenewingBoundState";
 
     /** @hide */
     public final String msg;
diff --git a/core/java/android/net/shared/FdEventsReader.java b/core/java/android/net/shared/FdEventsReader.java
index 5ccc560..bffbfb1 100644
--- a/core/java/android/net/shared/FdEventsReader.java
+++ b/core/java/android/net/shared/FdEventsReader.java
@@ -21,15 +21,15 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.net.util.SocketUtils;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.system.ErrnoException;
 import android.system.OsConstants;
 
-import libcore.io.IoUtils;
-
 import java.io.FileDescriptor;
+import java.io.IOException;
 
 
 /**
@@ -81,7 +81,10 @@
     private long mPacketsReceived;
 
     protected static void closeFd(FileDescriptor fd) {
-        IoUtils.closeQuietly(fd);
+        try {
+            SocketUtils.closeSocket(fd);
+        } catch (IOException ignored) {
+        }
     }
 
     protected FdEventsReader(@NonNull Handler h, @NonNull BufferType buffer) {
@@ -136,8 +139,8 @@
     }
 
     /**
-     * Subclasses MUST create the listening socket here, including setting
-     * all desired socket options, interface or address/port binding, etc.
+     * Subclasses MUST create the listening socket here, including setting all desired socket
+     * options, interface or address/port binding, etc. The socket MUST be created nonblocking.
      */
     @Nullable
     protected abstract FileDescriptor createFd();
@@ -181,10 +184,6 @@
 
         try {
             mFd = createFd();
-            if (mFd != null) {
-                // Force the socket to be non-blocking.
-                IoUtils.setBlocking(mFd, false);
-            }
         } catch (Exception e) {
             logError("Failed to create socket: ", e);
             closeFd(mFd);
diff --git a/core/java/android/net/shared/InetAddressUtils.java b/core/java/android/net/shared/InetAddressUtils.java
new file mode 100644
index 0000000..c9ee3a7
--- /dev/null
+++ b/core/java/android/net/shared/InetAddressUtils.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.shared;
+
+import android.os.Parcel;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Collection of utilities to interact with {@link InetAddress}
+ * @hide
+ */
+public class InetAddressUtils {
+
+    /**
+     * Writes an InetAddress to a parcel. The address may be null. This is likely faster than
+     * calling writeSerializable.
+     * @hide
+     */
+    public static void parcelInetAddress(Parcel parcel, InetAddress address, int flags) {
+        byte[] addressArray = (address != null) ? address.getAddress() : null;
+        parcel.writeByteArray(addressArray);
+    }
+
+    /**
+     * Reads an InetAddress from a parcel. Returns null if the address that was written was null
+     * or if the data is invalid.
+     * @hide
+     */
+    public static InetAddress unparcelInetAddress(Parcel in) {
+        byte[] addressArray = in.createByteArray();
+        if (addressArray == null) {
+            return null;
+        }
+        try {
+            return InetAddress.getByAddress(addressArray);
+        } catch (UnknownHostException e) {
+            return null;
+        }
+    }
+
+    private InetAddressUtils() {}
+}
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 141d33b..1f33693 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -19,6 +19,7 @@
 import android.annotation.MainThread;
 import android.annotation.Nullable;
 import android.annotation.WorkerThread;
+
 import java.util.ArrayDeque;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Callable;
@@ -70,7 +71,7 @@
  *     protected Long doInBackground(URL... urls) {
  *         int count = urls.length;
  *         long totalSize = 0;
- *         for (int i = 0; i < count; i++) {
+ *         for (int i = 0; i &lt; count; i++) {
  *             totalSize += Downloader.downloadFile(urls[i]);
  *             publishProgress((int) ((i / (float) count) * 100));
  *             // Escape early if cancel() is called
@@ -158,13 +159,22 @@
  * </ul>
  *
  * <h2>Memory observability</h2>
- * <p>AsyncTask guarantees that all callback calls are synchronized in such a way that the following
- * operations are safe without explicit synchronizations.</p>
+ * <p>AsyncTask guarantees that all callback calls are synchronized to ensure the following
+ * without explicit synchronizations.</p>
  * <ul>
- *     <li>Set member fields in the constructor or {@link #onPreExecute}, and refer to them
- *     in {@link #doInBackground}.
- *     <li>Set member fields in {@link #doInBackground}, and refer to them in
- *     {@link #onProgressUpdate} and {@link #onPostExecute}.
+ *     <li>The memory effects of {@link #onPreExecute}, and anything else
+ *     executed before the call to {@link #execute}, including the construction
+ *     of the AsyncTask object, are visible to {@link #doInBackground}.
+ *     <li>The memory effects of {@link #doInBackground} are visible to
+ *     {@link #onPostExecute}.
+ *     <li>Any memory effects of {@link #doInBackground} preceding a call
+ *     to {@link #publishProgress} are visible to the corresponding
+ *     {@link #onProgressUpdate} call. (But {@link #doInBackground} continues to
+ *     run, and care needs to be taken that later updates in {@link #doInBackground}
+ *     do not interfere with an in-progress {@link #onProgressUpdate} call.)
+ *     <li>Any memory effects preceding a call to {@link #cancel} are visible
+ *     after a call to {@link #isCancelled} that returns true as a result, or
+ *     during and after a resulting call to {@link #onCancelled}.
  * </ul>
  *
  * <h2>Order of execution</h2>
@@ -388,6 +398,10 @@
      * specified parameters are the parameters passed to {@link #execute}
      * by the caller of this task.
      *
+     * This will normally run on a background thread. But to better
+     * support testing frameworks, it is recommended that this also tolerates
+     * direct execution on the foreground thread, as part of the {@link #execute} call.
+     *
      * This method can call {@link #publishProgress} to publish updates
      * on the UI thread.
      *
@@ -404,6 +418,8 @@
 
     /**
      * Runs on the UI thread before {@link #doInBackground}.
+     * Invoked directly by {@link #execute} or {@link #executeOnExecutor}.
+     * The default version does nothing.
      *
      * @see #onPostExecute
      * @see #doInBackground
@@ -414,7 +430,10 @@
 
     /**
      * <p>Runs on the UI thread after {@link #doInBackground}. The
-     * specified result is the value returned by {@link #doInBackground}.</p>
+     * specified result is the value returned by {@link #doInBackground}.
+     * To better support testing frameworks, it is recommended that this be
+     * written to tolerate direct execution as part of the execute() call.
+     * The default version does nothing.</p>
      * 
      * <p>This method won't be invoked if the task was cancelled.</p>
      *
@@ -432,6 +451,7 @@
     /**
      * Runs on the UI thread after {@link #publishProgress} is invoked.
      * The specified values are the values passed to {@link #publishProgress}.
+     * The default version does nothing.
      *
      * @param values The values indicating progress.
      *
@@ -466,7 +486,8 @@
     /**
      * <p>Applications should preferably override {@link #onCancelled(Object)}.
      * This method is invoked by the default implementation of
-     * {@link #onCancelled(Object)}.</p>
+     * {@link #onCancelled(Object)}.
+     * The default version does nothing.</p>
      * 
      * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
      * {@link #doInBackground(Object[])} has finished.</p>
@@ -504,12 +525,16 @@
      * an attempt to stop the task.</p>
      * 
      * <p>Calling this method will result in {@link #onCancelled(Object)} being
-     * invoked on the UI thread after {@link #doInBackground(Object[])}
-     * returns. Calling this method guarantees that {@link #onPostExecute(Object)}
-     * is never invoked. After invoking this method, you should check the
-     * value returned by {@link #isCancelled()} periodically from
-     * {@link #doInBackground(Object[])} to finish the task as early as
-     * possible.</p>
+     * invoked on the UI thread after {@link #doInBackground(Object[])} returns.
+     * Calling this method guarantees that onPostExecute(Object) is never
+     * subsequently invoked, even if <tt>cancel</tt> returns false, but
+     * {@link #onPostExecute} has not yet run.  To finish the
+     * task as early as possible, check {@link #isCancelled()} periodically from
+     * {@link #doInBackground(Object[])}.</p>
+     *
+     * <p>This only requests cancellation. It never waits for a running
+     * background task to terminate, even if <tt>mayInterruptIfRunning</tt> is
+     * true.</p>
      *
      * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
      *        task should be interrupted; otherwise, in-progress tasks are allowed
diff --git a/core/java/android/os/DynamicAndroidManager.java b/core/java/android/os/DynamicAndroidManager.java
new file mode 100644
index 0000000..5238896
--- /dev/null
+++ b/core/java/android/os/DynamicAndroidManager.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.gsi.GsiProgress;
+
+/**
+ * The DynamicAndroidManager offers a mechanism to use a new Android image temporarily. After the
+ * installation, the device can reboot into this image with a new created /data. This image will
+ * last until the next reboot and then the device will go back to the original image. However the
+ * installed image and the new created /data are not deleted but disabled. Thus the application can
+ * either re-enable the installed image by calling {@link #toggle} or use the {@link #remove} to
+ * delete it completely. In other words, there are three device states: no installation, installed
+ * and running. The procedure to install a DynamicAndroid starts with a {@link #startInstallation},
+ * followed by a series of {@link #write} and ends with a {@link commit}. Once the installation is
+ * complete, the device state changes from no installation to the installed state and a followed
+ * reboot will change its state to running. Note one instance of dynamic android can exist on a
+ * given device thus the {@link #startInstallation} will fail if the device is currently running a
+ * DynamicAndroid.
+ *
+ * @hide
+ */
+@SystemService(Context.DYNAMIC_ANDROID_SERVICE)
+public class DynamicAndroidManager {
+    private static final String TAG = "DynamicAndroidManager";
+
+    private final IDynamicAndroidService mService;
+
+    /** {@hide} */
+    public DynamicAndroidManager(IDynamicAndroidService service) {
+        mService = service;
+    }
+
+    /** The DynamicAndroidManager.Session represents a started session for the installation. */
+    public class Session {
+        private Session() {}
+        /**
+         * Write a chunk of the DynamicAndroid system image
+         *
+         * @return {@code true} if the call succeeds. {@code false} if there is any native runtime
+         *     error.
+         */
+        @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID)
+        public boolean write(byte[] buf) {
+            try {
+                return mService.write(buf);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e.toString());
+            }
+        }
+
+        /**
+         * Finish write and make device to boot into the it after reboot.
+         *
+         * @return {@code true} if the call succeeds. {@code false} if there is any native runtime
+         *     error.
+         */
+        @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID)
+        public boolean commit() {
+            try {
+                return mService.commit();
+            } catch (RemoteException e) {
+                throw new RuntimeException(e.toString());
+            }
+        }
+    }
+    /**
+     * Start DynamicAndroid installation. This call may take an unbounded amount of time. The caller
+     * may use another thread to call the getStartProgress() to get the progress.
+     *
+     * @param systemSize system size in bytes
+     * @param userdataSize userdata size in bytes
+     * @return {@code true} if the call succeeds. {@code false} either the device does not contain
+     *     enough space or a DynamicAndroid is currently in use where the {@link #isInUse} would be
+     *     true.
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID)
+    public Session startInstallation(long systemSize, long userdataSize) {
+        try {
+            if (mService.startInstallation(systemSize, userdataSize)) {
+                return new Session();
+            } else {
+                return null;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
+
+    /**
+     * Query the progress of the current installation operation. This can be called while the
+     * installation is in progress.
+     *
+     * @return GsiProgress GsiProgress { int status; long bytes_processed; long total_bytes; } The
+     *     status field can be IGsiService.STATUS_NO_OPERATION, IGsiService.STATUS_WORKING or
+     *     IGsiService.STATUS_COMPLETE.
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID)
+    public GsiProgress getInstallationProgress() {
+        try {
+            return mService.getInstallationProgress();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
+
+    /**
+     * Abort the installation process. Note this method must be called in a thread other than the
+     * one calling the startInstallation method as the startInstallation method will not return
+     * until it is finished.
+     *
+     * @return {@code true} if the call succeeds. {@code false} if there is no installation
+     *     currently.
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID)
+    public boolean abort() {
+        try {
+            return mService.abort();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
+
+    /** @return {@code true} if the device is running a dynamic android */
+    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID)
+    public boolean isInUse() {
+        try {
+            return mService.isInUse();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
+
+    /** @return {@code true} if the device has a dynamic android installed */
+    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID)
+    public boolean isInstalled() {
+        try {
+            return mService.isInstalled();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
+
+    /**
+     * Remove DynamicAndroid installation if present
+     *
+     * @return {@code true} if the call succeeds. {@code false} if there is no installed image.
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID)
+    public boolean remove() {
+        try {
+            return mService.remove();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
+
+    /**
+     * Enable DynamicAndroid when it's not enabled, otherwise, disable it.
+     *
+     * @return {@code true} if the call succeeds. {@code false} if there is no installed image.
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_ANDROID)
+    public boolean toggle() {
+        try {
+            return mService.toggle();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
+}
diff --git a/core/java/android/os/IDynamicAndroidService.aidl b/core/java/android/os/IDynamicAndroidService.aidl
new file mode 100644
index 0000000..0b28799
--- /dev/null
+++ b/core/java/android/os/IDynamicAndroidService.aidl
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os;
+
+import android.gsi.GsiProgress;
+
+/** {@hide} */
+interface IDynamicAndroidService
+{
+    /**
+     * Start DynamicAndroid installation. This call may take 60~90 seconds. The caller
+     * may use another thread to call the getStartProgress() to get the progress.
+     *
+     * @param systemSize system size in bytes
+     * @param userdataSize userdata size in bytes
+     * @return true if the call succeeds
+     */
+    boolean startInstallation(long systemSize, long userdataSize);
+
+    /**
+     * Query the progress of the current installation operation. This can be called while
+     * the installation is in progress.
+     *
+     * @return GsiProgress
+     */
+    GsiProgress getInstallationProgress();
+
+    /**
+     * Abort the installation process. Note this method must be called in a thread other
+     * than the one calling the startInstallation method as the startInstallation
+     * method will not return until it is finished.
+     *
+     * @return true if the call succeeds
+     */
+    boolean abort();
+
+    /**
+     * @return true if the device is running an DynamicAnroid image
+     */
+    boolean isInUse();
+
+    /**
+     * @return true if the device has an DynamicAndroid image installed
+     */
+    boolean isInstalled();
+
+    /**
+     * Remove DynamicAndroid installation if present
+     *
+     * @return true if the call succeeds
+     */
+    boolean remove();
+
+    /**
+     * Enable DynamicAndroid when it's not enabled, otherwise, disable it.
+     *
+     * @return true if the call succeeds
+     */
+    boolean toggle();
+
+    /**
+     * Write a chunk of the DynamicAndroid system image
+     *
+     * @return true if the call succeeds
+     */
+    boolean write(in byte[] buf);
+
+    /**
+     * Finish write and make device to boot into the it after reboot.
+     *
+     * @return true if the call succeeds
+     */
+    boolean commit();
+}
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
new file mode 100644
index 0000000..b568f15
--- /dev/null
+++ b/core/java/android/os/OWNERS
@@ -0,0 +1,2 @@
+# Zygote
+per-file ZygoteProcess.java = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 648c022..de41ce2 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -226,6 +226,7 @@
      * @hide
      */
     @TestApi
+    @SystemApi
     public static @AppIdInt int getAppId(int uid) {
         return uid % PER_USER_RANGE;
     }
diff --git a/core/java/android/service/dreams/OWNERS b/core/java/android/service/dreams/OWNERS
index 3c9bbf8..426f002 100644
--- a/core/java/android/service/dreams/OWNERS
+++ b/core/java/android/service/dreams/OWNERS
@@ -1,3 +1,3 @@
-dsandler@google.com
+dsandler@android.com
 michaelwr@google.com
 roosa@google.com
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index f2259b0..2ee72bf 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
@@ -389,9 +390,13 @@
     }
 
     private void initPrecompiledViews() {
+        initPrecompiledViews(
+                SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false));
+    }
+
+    private void initPrecompiledViews(boolean enablePrecompiledViews) {
+        mUseCompiledView = enablePrecompiledViews;
         try {
-            mUseCompiledView =
-                SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false);
             if (mUseCompiledView) {
                 mPrecompiledClassLoader = mContext.getClassLoader();
                 String dexFile = mContext.getCodeCacheDir() + COMPILED_VIEW_DEX_FILE_NAME;
@@ -409,6 +414,17 @@
             }
             mUseCompiledView = false;
         }
+        if (!mUseCompiledView) {
+            mPrecompiledClassLoader = null;
+        }
+    }
+
+    /**
+     * @hide for use by CTS tests
+     */
+    @TestApi
+    public void setPrecompiledLayoutsEnabledForTesting(boolean enablePrecompiledLayouts) {
+        initPrecompiledViews(enablePrecompiledLayouts);
     }
 
     /**
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index da8605e..65b974b 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -104,6 +104,7 @@
     public boolean allowBypass;
     public boolean allowIPv4;
     public boolean allowIPv6;
+    public boolean isMetered = true;
     public Network[] underlyingNetworks;
     public ProxyInfo proxyInfo;
 
@@ -165,6 +166,7 @@
         out.writeInt(allowBypass ? 1 : 0);
         out.writeInt(allowIPv4 ? 1 : 0);
         out.writeInt(allowIPv6 ? 1 : 0);
+        out.writeInt(isMetered ? 1 : 0);
         out.writeTypedArray(underlyingNetworks, flags);
         out.writeParcelable(proxyInfo, flags);
     }
@@ -191,6 +193,7 @@
             config.allowBypass = in.readInt() != 0;
             config.allowIPv4 = in.readInt() != 0;
             config.allowIPv6 = in.readInt() != 0;
+            config.isMetered = in.readInt() != 0;
             config.underlyingNetworks = in.createTypedArray(Network.CREATOR);
             config.proxyInfo = in.readParcelable(null);
             return config;
diff --git a/core/java/com/android/internal/os/OWNERS b/core/java/com/android/internal/os/OWNERS
new file mode 100644
index 0000000..9283105
--- /dev/null
+++ b/core/java/com/android/internal/os/OWNERS
@@ -0,0 +1 @@
+per-file ZygoteArguments.java,ZygoteConnection.java,ZygoteInit.java,Zygote.java,ZygoteServer.java = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 3859b95..1048cb4 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -120,8 +120,6 @@
      * */
     protected static FileDescriptor sBlastulaPoolEventFD;
 
-    private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
-
     /**
      * An extraArg passed when a zygote process is forking a child-zygote, specifying a name
      * in the abstract socket namespace. This socket name is what the new child zygote
@@ -213,7 +211,7 @@
     public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
             int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
             int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) {
-        VM_HOOKS.preFork();
+        ZygoteHooks.preFork();
         // Resets nice priority for zygote process.
         resetNicePriority();
         int pid = nativeForkAndSpecialize(
@@ -226,7 +224,7 @@
             // Note that this event ends at the end of handleChildProc,
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
         }
-        VM_HOOKS.postForkCommon();
+        ZygoteHooks.postForkCommon();
         return pid;
     }
 
@@ -275,7 +273,7 @@
          *
          * TODO (chriswailes): Look into moving this to immediately after the fork.
          */
-        VM_HOOKS.postForkCommon();
+        ZygoteHooks.postForkCommon();
     }
 
     private static native void nativeSpecializeBlastula(int uid, int gid, int[] gids,
@@ -312,7 +310,7 @@
      */
     public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
             int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
-        VM_HOOKS.preFork();
+        ZygoteHooks.preFork();
         // Resets nice priority for zygote process.
         resetNicePriority();
         int pid = nativeForkSystemServer(
@@ -322,7 +320,7 @@
         if (pid == 0) {
             Trace.setTracingEnabled(true, runtimeFlags);
         }
-        VM_HOOKS.postForkCommon();
+        ZygoteHooks.postForkCommon();
         return pid;
     }
 
@@ -390,7 +388,7 @@
 
             // Disable some VM functionality and reset some system values
             // before forking.
-            VM_HOOKS.preFork();
+            ZygoteHooks.preFork();
             resetNicePriority();
 
             while (blastulaPoolCount++ < sBlastulaPoolMax) {
@@ -403,7 +401,7 @@
 
             // Re-enable runtime services for the Zygote.  Blastula services
             // are re-enabled in specializeBlastula.
-            VM_HOOKS.postForkCommon();
+            ZygoteHooks.postForkCommon();
 
             Log.i("zygote", "Filled the blastula pool. New blastulas: " + numBlastulasToSpawn);
         }
@@ -817,12 +815,12 @@
 
     private static void callPostForkSystemServerHooks() {
         // SystemServer specific post fork hooks run before child post fork hooks.
-        VM_HOOKS.postForkSystemServer();
+        ZygoteHooks.postForkSystemServer();
     }
 
     private static void callPostForkChildHooks(int runtimeFlags, boolean isSystemServer,
             boolean isZygote, String instructionSet) {
-        VM_HOOKS.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet);
+        ZygoteHooks.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet);
     }
 
     /**
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index ab356a6..2bb0759 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -26,6 +26,7 @@
 import static com.android.internal.os.ZygoteConnectionConstants.CONNECTION_TIMEOUT_MILLIS;
 import static com.android.internal.os.ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS;
 
+import android.metrics.LogMaker;
 import android.net.Credentials;
 import android.net.LocalSocket;
 import android.os.Process;
@@ -35,6 +36,9 @@
 import android.system.StructPollfd;
 import android.util.Log;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
 import dalvik.system.VMRuntime;
 
 import libcore.io.IoUtils;
@@ -311,9 +315,43 @@
         }
     }
 
-    private void handleHiddenApiAccessLogSampleRate(int percent) {
+    private class HiddenApiUsageLogger implements VMRuntime.HiddenApiUsageLogger {
+
+        private final MetricsLogger mMetricsLogger = new MetricsLogger();
+
+        public void hiddenApiUsed(String packageName, String signature,
+                int accessMethod, boolean accessDenied) {
+            int accessMethodMetric = HiddenApiUsageLogger.ACCESS_METHOD_NONE;
+            switch(accessMethod) {
+                case HiddenApiUsageLogger.ACCESS_METHOD_NONE:
+                    accessMethodMetric = MetricsEvent.ACCESS_METHOD_NONE;
+                    break;
+                case HiddenApiUsageLogger.ACCESS_METHOD_REFLECTION:
+                    accessMethodMetric = MetricsEvent.ACCESS_METHOD_REFLECTION;
+                    break;
+                case HiddenApiUsageLogger.ACCESS_METHOD_JNI:
+                    accessMethodMetric = MetricsEvent.ACCESS_METHOD_JNI;
+                    break;
+                case HiddenApiUsageLogger.ACCESS_METHOD_LINKING:
+                    accessMethodMetric = MetricsEvent.ACCESS_METHOD_LINKING;
+                    break;
+            }
+            LogMaker logMaker = new LogMaker(MetricsEvent.ACTION_HIDDEN_API_ACCESSED)
+                    .setPackageName(packageName)
+                    .addTaggedData(MetricsEvent.FIELD_HIDDEN_API_SIGNATURE, signature)
+                    .addTaggedData(MetricsEvent.FIELD_HIDDEN_API_ACCESS_METHOD,
+                        accessMethodMetric);
+            if (accessDenied) {
+                logMaker.addTaggedData(MetricsEvent.FIELD_HIDDEN_API_ACCESS_DENIED, 1);
+            }
+            mMetricsLogger.write(logMaker);
+        }
+    }
+
+    private void handleHiddenApiAccessLogSampleRate(int samplingRate) {
         try {
-            ZygoteInit.setHiddenApiAccessLogSampleRate(percent);
+            ZygoteInit.setHiddenApiAccessLogSampleRate(samplingRate);
+            ZygoteInit.setHiddenApiUsageLogger(new HiddenApiUsageLogger());
             mSocketOutStream.writeInt(0);
         } catch (IOException ioe) {
             throw new IllegalStateException("Error writing to command socket", ioe);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index e3e55ed..9f23797 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -533,6 +533,14 @@
     }
 
     /**
+     * Sets the implementation to be used for logging hidden API accesses
+     * @param logger the implementation of the VMRuntime.HiddenApiUsageLogger interface
+     */
+    public static void setHiddenApiUsageLogger(VMRuntime.HiddenApiUsageLogger logger) {
+        VMRuntime.getRuntime().setHiddenApiUsageLogger(logger);
+    }
+
+    /**
      * Creates a PathClassLoader for the given class path that is associated with a shared
      * namespace, i.e., this classloader can access platform-private native libraries. The
      * classloader will use java.library.path as the native library path.
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index a365a56..86342c4 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -4,3 +4,6 @@
 
 # Connectivity
 per-file android_net_* = ek@google.com, lorenzo@google.com, satk@google.com
+
+# Zygote
+per-file com_android_inernal_os_Zygote.*,fd_utils.* = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index e64d2af..ee11b61 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -96,7 +96,7 @@
     return toJavaStringArray(env, cStrings);
 }
 
-static jint verify(JNIEnv* env, jobjectArray packageInfo, android::vintf::CheckFlags::Type checks) {
+static jint android_os_VintfObject_verify(JNIEnv* env, jclass, jobjectArray packageInfo) {
     std::vector<std::string> cPackageInfo;
     if (packageInfo) {
         size_t count = env->GetArrayLength(packageInfo);
@@ -109,18 +109,19 @@
         }
     }
     std::string error;
-    int32_t status = VintfObject::CheckCompatibility(cPackageInfo, &error, checks);
+    int32_t status = VintfObject::CheckCompatibility(cPackageInfo, &error);
     if (status)
         LOG(WARNING) << "VintfObject.verify() returns " << status << ": " << error;
     return status;
 }
 
-static jint android_os_VintfObject_verify(JNIEnv* env, jclass, jobjectArray packageInfo) {
-    return verify(env, packageInfo, ::android::vintf::CheckFlags::ENABLE_ALL_CHECKS);
-}
-
 static jint android_os_VintfObject_verifyWithoutAvb(JNIEnv* env, jclass) {
-    return verify(env, nullptr, ::android::vintf::CheckFlags::DISABLE_AVB_CHECK);
+    std::string error;
+    int32_t status = VintfObject::CheckCompatibility({}, &error,
+            ::android::vintf::CheckFlags::DISABLE_AVB_CHECK);
+    if (status)
+        LOG(WARNING) << "VintfObject.verifyWithoutAvb() returns " << status << ": " << error;
+    return status;
 }
 
 static jobjectArray android_os_VintfObject_getHalNamesAndVersions(JNIEnv* env, jclass) {
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 9782541..32ddad1 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -346,30 +346,34 @@
 static void get_cpuset_cores_for_policy(SchedPolicy policy, cpu_set_t *cpu_set)
 {
     FILE *file;
-    const char *filename;
+    std::string filename;
 
     CPU_ZERO(cpu_set);
 
     switch (policy) {
         case SP_BACKGROUND:
-            filename = "/dev/cpuset/background/cpus";
+            if (!CgroupGetAttributePath("LowCapacityCPUs", &filename)) {
+                return;
+            }
             break;
         case SP_FOREGROUND:
         case SP_AUDIO_APP:
         case SP_AUDIO_SYS:
         case SP_RT_APP:
-            filename = "/dev/cpuset/foreground/cpus";
+            if (!CgroupGetAttributePath("HighCapacityCPUs", &filename)) {
+                return;
+            }
             break;
         case SP_TOP_APP:
-            filename = "/dev/cpuset/top-app/cpus";
+            if (!CgroupGetAttributePath("MaxCapacityCPUs", &filename)) {
+                return;
+            }
             break;
         default:
-            filename = NULL;
+            return;
     }
 
-    if (!filename) return;
-
-    file = fopen(filename, "re");
+    file = fopen(filename.c_str(), "re");
     if (file != NULL) {
         // Parse cpus string
         char *line = NULL;
@@ -379,7 +383,7 @@
         if (num_read > 0) {
             parse_cpuset_cpus(line, cpu_set);
         } else {
-            ALOGE("Failed to read %s", filename);
+            ALOGE("Failed to read %s", filename.c_str());
         }
         free(line);
     }
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 1448d7b..3012c90 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1305,15 +1305,12 @@
           RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
       }
 
-      bool low_ram_device = GetBoolProperty("ro.config.low_ram", false);
-      bool per_app_memcg = GetBoolProperty("ro.config.per_app_memcg", low_ram_device);
-      if (per_app_memcg) {
+      if (UsePerAppMemcg()) {
           // Assign system_server to the correct memory cgroup.
-          // Not all devices mount /dev/memcg so check for the file first
+          // Not all devices mount memcg so check if it is mounted first
           // to avoid unnecessarily printing errors and denials in the logs.
-          if (!access("/dev/memcg/system/tasks", F_OK) &&
-                !WriteStringToFile(StringPrintf("%d", pid), "/dev/memcg/system/tasks")) {
-              ALOGE("couldn't write %d to /dev/memcg/system/tasks", pid);
+          if (!SetTaskProfiles(pid, std::vector<std::string>{"SystemMemoryProcess"})) {
+              ALOGE("couldn't add process %d into system memcg group", pid);
           }
       }
   }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2f3c1db..9a7e8dd 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1554,7 +1554,7 @@
     <permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"
         android:protectionLevel="signature|privileged" />
 
-    <!-- Allows a system application to access hardware packet offload capabilities.
+    <!-- @SystemApi Allows a system application to access hardware packet offload capabilities.
          @hide -->
     <permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD"
         android:protectionLevel="signature|privileged" />
@@ -1681,6 +1681,10 @@
     <permission android:name="android.permission.HARDWARE_TEST"
         android:protectionLevel="signature" />
 
+    <!-- @hide Allows an application to manage DynamicAndroid image -->
+    <permission android:name="android.permission.MANAGE_DYNAMIC_ANDROID"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi Allows access to Broadcast Radio
          @hide This is not a third-party API (intended for system apps).-->
     <permission android:name="android.permission.ACCESS_BROADCAST_RADIO"
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index 035ee10..bb47658 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -58,6 +58,14 @@
 }
 
 prebuilt_etc {
+    name: "privapp_whitelist_com.android.dialer",
+    product_specific: true,
+    sub_dir: "permissions",
+    src: "com.android.dialer.xml",
+    filename_from_src: true,
+}
+
+prebuilt_etc {
     name: "privapp_whitelist_com.android.launcher3",
     product_specific: true,
     sub_dir: "permissions",
diff --git a/data/etc/com.android.dialer.xml b/data/etc/com.android.dialer.xml
new file mode 100644
index 0000000..ccdb21f
--- /dev/null
+++ b/data/etc/com.android.dialer.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<permissions>
+    <privapp-permissions package="com.android.dialer">
+        <permission name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"/>
+        <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
+        <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
+        <permission name="android.permission.MODIFY_PHONE_STATE"/>
+        <permission name="android.permission.STATUS_BAR"/>
+        <permission name="android.permission.STOP_APP_SWITCHES"/>
+        <permission name="com.android.voicemail.permission.READ_VOICEMAIL"/>
+        <permission name="com.android.voicemail.permission.WRITE_VOICEMAIL"/>
+    </privapp-permissions>
+</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c9f0f10..9a148e4 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -48,17 +48,6 @@
         <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
     </privapp-permissions>
 
-    <privapp-permissions package="com.android.dialer">
-        <permission name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"/>
-        <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
-        <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
-        <permission name="android.permission.MODIFY_PHONE_STATE"/>
-        <permission name="android.permission.STATUS_BAR"/>
-        <permission name="android.permission.STOP_APP_SWITCHES"/>
-        <permission name="com.android.voicemail.permission.READ_VOICEMAIL"/>
-        <permission name="com.android.voicemail.permission.WRITE_VOICEMAIL"/>
-    </privapp-permissions>
-
     <privapp-permissions package="com.android.emergency">
         <!-- Required to place emergency calls from emergency info screen. -->
         <permission name="android.permission.CALL_PRIVILEGED"/>
diff --git a/keystore/java/android/security/OWNERS b/keystore/java/android/security/OWNERS
new file mode 100644
index 0000000..ed30587
--- /dev/null
+++ b/keystore/java/android/security/OWNERS
@@ -0,0 +1 @@
+per-file *.java,*.aidl = eranm@google.com,pgrafov@google.com,rubinxu@google.com
diff --git a/keystore/tests/OWNERS b/keystore/tests/OWNERS
new file mode 100644
index 0000000..9e65f88
--- /dev/null
+++ b/keystore/tests/OWNERS
@@ -0,0 +1,5 @@
+# Android Enterprise security team
+eranm@google.com
+irinaid@google.com
+pgrafov@google.com
+rubinxu@google.com
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 4c563db..25c7b5c 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -51,6 +51,7 @@
         "libmtp",
         "libexif",
         "libpiex",
+        "libprocessgroup",
         "libandroidfw",
         "libhidlallocatorutils",
         "libhidlbase",
@@ -131,6 +132,7 @@
         "libcutils",
         "libdexfile",
         "liblzma",
+        "libjsoncpp",
         "libmedia_helper",
         "libmedia_player2_util",
         "libmediadrm",
@@ -140,6 +142,7 @@
         "libmediautils",
         "libnativehelper",
         "libnetd_client",
+        "libprocessgroup",
         "libstagefright_esds",
         "libstagefright_foundation",
         "libstagefright_httplive",
diff --git a/packages/CaptivePortalLogin/Android.bp b/packages/CaptivePortalLogin/Android.bp
new file mode 100644
index 0000000..4ac652a
--- /dev/null
+++ b/packages/CaptivePortalLogin/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_app {
+    name: "CaptivePortalLogin",
+    srcs: ["src/**/*.java"],
+    sdk_version: "system_current",
+    certificate: "platform",
+    static_libs: [
+        "android-support-v4",
+        "metrics-constants-protos",
+    ],
+    manifest: "AndroidManifest.xml",
+}
diff --git a/packages/CaptivePortalLogin/Android.mk b/packages/CaptivePortalLogin/Android.mk
deleted file mode 100644
index 7dc23ff..0000000
--- a/packages/CaptivePortalLogin/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CaptivePortalLogin
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index c84f3ec..e15dca0 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -21,7 +21,8 @@
 
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
     <uses-permission android:name="android.permission.NETWORK_BYPASS_PRIVATE_DNS" />
 
diff --git a/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml b/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml
deleted file mode 100644
index d460041..0000000
--- a/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/ssl_error_msg"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:textAppearance="?android:attr/textAppearanceSmall"
-    android:layout_marginStart="20dip"
-    android:layout_marginEnd="20dip"
-    android:gravity="center_vertical"
-    android:layout_marginBottom="4dip"
-    android:layout_marginTop="4dip" />
-
diff --git a/packages/CaptivePortalLogin/res/layout/ssl_warning.xml b/packages/CaptivePortalLogin/res/layout/ssl_warning.xml
index ffd57a4..ce05e78 100644
--- a/packages/CaptivePortalLogin/res/layout/ssl_warning.xml
+++ b/packages/CaptivePortalLogin/res/layout/ssl_warning.xml
@@ -78,7 +78,18 @@
             android:id="@+id/certificate_layout"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:orientation="vertical"
             android:layout_marginBottom="16dip" >
+            <TextView
+                android:id="@+id/ssl_error_msg"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:layout_marginStart="20dip"
+                android:layout_marginEnd="20dip"
+                android:gravity="center_vertical"
+                android:layout_marginBottom="4dip"
+                android:layout_marginTop="16dip" />
         </LinearLayout>
 
     </ScrollView>
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index d03e5e3..9b70ff3 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -20,7 +20,7 @@
 
 import android.app.Activity;
 import android.app.AlertDialog;
-import android.app.LoadedApk;
+import android.app.Application;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -37,8 +37,9 @@
 import android.net.http.SslCertificate;
 import android.net.http.SslError;
 import android.net.wifi.WifiInfo;
-import android.os.Build;
+import android.net.wifi.WifiManager;
 import android.os.Bundle;
+import android.os.SystemProperties;
 import android.support.v4.widget.SwipeRefreshLayout;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -59,7 +60,6 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 import java.io.IOException;
@@ -96,6 +96,7 @@
     private CaptivePortal mCaptivePortal;
     private NetworkCallback mNetworkCallback;
     private ConnectivityManager mCm;
+    private WifiManager mWifiManager;
     private boolean mLaunchBrowser = false;
     private MyWebViewClient mWebViewClient;
     private SwipeRefreshLayout mSwipeRefreshLayout;
@@ -106,11 +107,12 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
         logMetricsEvent(MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY);
 
-        mCm = ConnectivityManager.from(this);
+        mCm = getSystemService(ConnectivityManager.class);
+        mWifiManager = getSystemService(WifiManager.class);
         mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
-        mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
         mUserAgent =
                 getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT);
         mUrl = getUrl();
@@ -151,7 +153,6 @@
         // Also initializes proxy system properties.
         mNetwork = mNetwork.getPrivateDnsBypassingCopy();
         mCm.bindProcessToNetwork(mNetwork);
-        mCm.setProcessDefaultNetworkForHostResolution(mNetwork);
 
         // Proxy system properties must be initialized before setContentView is called because
         // setContentView initializes the WebView logic which in turn reads the system properties.
@@ -190,9 +191,12 @@
 
     // Find WebView's proxy BroadcastReceiver and prompt it to read proxy system properties.
     private void setWebViewProxy() {
-        LoadedApk loadedApk = getApplication().mLoadedApk;
+        // TODO: migrate to androidx WebView proxy setting API as soon as it is finalized
         try {
-            Field receiversField = LoadedApk.class.getDeclaredField("mReceivers");
+            final Field loadedApkField = Application.class.getDeclaredField("mLoadedApk");
+            final Class<?> loadedApkClass = loadedApkField.getType();
+            final Object loadedApk = loadedApkField.get(getApplication());
+            Field receiversField = loadedApkClass.getDeclaredField("mReceivers");
             receiversField.setAccessible(true);
             ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
             for (Object receiverMap : receivers.values()) {
@@ -333,7 +337,11 @@
 
     private static String sanitizeURL(URL url) {
         // In non-Debug build, only show host to avoid leaking private info.
-        return Build.IS_DEBUGGABLE ? Objects.toString(url) : host(url);
+        return isDebuggable() ? Objects.toString(url) : host(url);
+    }
+
+    private static boolean isDebuggable() {
+        return SystemProperties.getInt("ro.debuggable", 0) == 1;
     }
 
     private void testForCaptivePortal() {
@@ -586,19 +594,18 @@
         }
 
         private void setViewSecurityCertificate(LinearLayout certificateLayout, SslError error) {
+            ((TextView) certificateLayout.findViewById(R.id.ssl_error_msg))
+                    .setText(sslErrorMessage(error));
             SslCertificate cert = error.getCertificate();
-
-            View certificateView = cert.inflateCertificateView(CaptivePortalLoginActivity.this);
-            final LinearLayout placeholder = (LinearLayout) certificateView
-                    .findViewById(com.android.internal.R.id.placeholder);
-            LayoutInflater factory = LayoutInflater.from(CaptivePortalLoginActivity.this);
-
-            TextView textView = (TextView) factory.inflate(
-                    R.layout.ssl_error_msg, placeholder, false);
-            textView.setText(sslErrorMessage(error));
-            placeholder.addView(textView);
-
-            certificateLayout.addView(certificateView);
+            // TODO: call the method directly once inflateCertificateView is @SystemApi
+            try {
+                final View certificateView = (View) SslCertificate.class.getMethod(
+                        "inflateCertificateView", Context.class)
+                        .invoke(cert, CaptivePortalLoginActivity.this);
+                certificateLayout.addView(certificateView);
+            } catch (ReflectiveOperationException | SecurityException e) {
+                Log.e(TAG, "Could not create certificate view", e);
+            }
         }
     }
 
@@ -619,11 +626,30 @@
 
     private String getHeaderTitle() {
         NetworkCapabilities nc = mCm.getNetworkCapabilities(mNetwork);
-        if (nc == null || TextUtils.isEmpty(nc.getSSID())
-            || !nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
+        final String ssid = getSsid();
+        if (TextUtils.isEmpty(ssid)
+                || nc == null || !nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
             return getString(R.string.action_bar_label);
         }
-        return getString(R.string.action_bar_title, WifiInfo.removeDoubleQuotes(nc.getSSID()));
+        return getString(R.string.action_bar_title, ssid);
+    }
+
+    // TODO: remove once SSID is obtained from NetworkCapabilities
+    private String getSsid() {
+        if (mWifiManager == null) {
+            return null;
+        }
+        final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+        return removeDoubleQuotes(wifiInfo.getSSID());
+    }
+
+    private static String removeDoubleQuotes(String string) {
+        if (string == null) return null;
+        final int length = string.length();
+        if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
+            return string.substring(1, length - 1);
+        }
+        return string;
     }
 
     private String getHeaderSubtitle(URL url) {
@@ -636,7 +662,7 @@
     }
 
     private void logMetricsEvent(int event) {
-        MetricsLogger.action(this, event, getPackageName());
+        mCaptivePortal.logEvent(event, getPackageName());
     }
 
     private static final SparseArray<String> SSL_ERRORS = new SparseArray<>();
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index 9b0d896..d656593 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -18,6 +18,7 @@
 // system server on devices that run the stack there
 java_library {
     name: "NetworkStackLib",
+    sdk_version: "system_current",
     installable: true,
     srcs: [
         "src/**/*.java",
@@ -25,18 +26,20 @@
         ":services-networkstack-shared-srcs",
     ],
     static_libs: [
-        "services-netlink-lib",
+        "netd_aidl_interface-java",
+        "networkstack-aidl-interfaces-java",
     ]
 }
 
 // Updatable network stack packaged as an application
 android_app {
     name: "NetworkStack",
-    platform_apis: true,
+    sdk_version: "system_current",
     certificate: "platform",
     privileged: true,
     static_libs: [
         "NetworkStackLib"
     ],
     manifest: "AndroidManifest.xml",
+    required: ["NetworkStackPermissionStub"],
 }
\ No newline at end of file
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index 5ab833b..ac55bfa 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -25,6 +25,8 @@
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
     <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
+    <!-- Signature permission defined in NetworkStackStub -->
+    <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
     <!-- Launch captive portal app as specific user -->
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.NETWORK_STACK" />
diff --git a/packages/NetworkStack/src/android/net/apf/ApfFilter.java b/packages/NetworkStack/src/android/net/apf/ApfFilter.java
index 08452bb..4fa7d64 100644
--- a/packages/NetworkStack/src/android/net/apf/ApfFilter.java
+++ b/packages/NetworkStack/src/android/net/apf/ApfFilter.java
@@ -38,7 +38,6 @@
 import android.content.IntentFilter;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
-import android.net.NetworkUtils;
 import android.net.apf.ApfGenerator.IllegalInstructionException;
 import android.net.apf.ApfGenerator.Register;
 import android.net.ip.IpClient.IpClientCallbacksWrapper;
@@ -47,6 +46,8 @@
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.RaEvent;
 import android.net.util.InterfaceParams;
+import android.net.util.NetworkStackUtils;
+import android.net.util.SocketUtils;
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.system.ErrnoException;
@@ -60,8 +61,6 @@
 import com.android.internal.util.HexDump;
 import com.android.internal.util.IndentingPrintWriter;
 
-import libcore.io.IoBridge;
-
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.net.Inet4Address;
@@ -200,10 +199,8 @@
 
         public void halt() {
             mStopped = true;
-            try {
-                // Interrupts the read() call the thread is blocked in.
-                IoBridge.closeAndSignalBlockedThreads(mSocket);
-            } catch (IOException ignored) {}
+            // Interrupts the read() call the thread is blocked in.
+            NetworkStackUtils.closeSocketQuietly(mSocket);
         }
 
         @Override
@@ -470,8 +467,8 @@
             socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
             SocketAddress addr = makePacketSocketAddress(
                     (short) ETH_P_IPV6, mInterfaceParams.index);
-            Os.bind(socket, addr);
-            NetworkUtils.attachRaFilter(socket, mApfCapabilities.apfPacketFormat);
+            SocketUtils.bindSocket(socket, addr);
+            SocketUtils.attachRaFilter(socket, mApfCapabilities.apfPacketFormat);
         } catch(SocketException|ErrnoException e) {
             Log.e(TAG, "Error starting filter", e);
             return;
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
index 12eecc0..b0e8da9 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
@@ -28,6 +28,7 @@
 import static android.net.dhcp.DhcpPacket.DHCP_VENDOR_INFO;
 import static android.net.dhcp.DhcpPacket.INADDR_ANY;
 import static android.net.dhcp.DhcpPacket.INADDR_BROADCAST;
+import static android.net.util.NetworkStackUtils.closeSocketQuietly;
 import static android.net.util.SocketUtils.makePacketSocketAddress;
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.AF_PACKET;
@@ -44,7 +45,6 @@
 
 import android.content.Context;
 import android.net.DhcpResults;
-import android.net.NetworkUtils;
 import android.net.TrafficStats;
 import android.net.ip.IpClient;
 import android.net.metrics.DhcpClientEvent;
@@ -66,8 +66,6 @@
 import com.android.internal.util.StateMachine;
 import com.android.internal.util.WakeupMessage;
 
-import libcore.io.IoBridge;
-
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.net.Inet4Address;
@@ -108,6 +106,12 @@
     private static final boolean MSG_DBG = false;
     private static final boolean PACKET_DBG = false;
 
+    // Metrics events: must be kept in sync with server-side aggregation code.
+    /** Represents transitions from DhcpInitState to DhcpBoundState */
+    private static final String EVENT_INITIAL_BOUND = "InitialBoundState";
+    /** Represents transitions from and to DhcpBoundState via DhcpRenewingState */
+    private static final String EVENT_RENEWING_BOUND = "RenewingBoundState";
+
     // Timers and timeouts.
     private static final int SECONDS = 1000;
     private static final int FIRST_TIMEOUT_MS   =   2 * SECONDS;
@@ -313,8 +317,8 @@
         try {
             mPacketSock = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IP);
             SocketAddress addr = makePacketSocketAddress((short) ETH_P_IP, mIface.index);
-            Os.bind(mPacketSock, addr);
-            NetworkUtils.attachDhcpFilter(mPacketSock);
+            SocketUtils.bindSocket(mPacketSock, addr);
+            SocketUtils.attachDhcpFilter(mPacketSock);
         } catch(SocketException|ErrnoException e) {
             Log.e(TAG, "Error creating packet socket", e);
             return false;
@@ -350,15 +354,9 @@
         }
     }
 
-    private static void closeQuietly(FileDescriptor fd) {
-        try {
-            IoBridge.closeAndSignalBlockedThreads(fd);
-        } catch (IOException ignored) {}
-    }
-
     private void closeSockets() {
-        closeQuietly(mUdpSock);
-        closeQuietly(mPacketSock);
+        closeSocketQuietly(mUdpSock);
+        closeSocketQuietly(mPacketSock);
     }
 
     class ReceiveThread extends Thread {
@@ -414,7 +412,8 @@
         try {
             if (encap == DhcpPacket.ENCAP_L2) {
                 if (DBG) Log.d(TAG, "Broadcasting " + description);
-                Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
+                SocketUtils.sendTo(
+                        mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
             } else if (encap == DhcpPacket.ENCAP_BOOTP && to.equals(INADDR_BROADCAST)) {
                 if (DBG) Log.d(TAG, "Broadcasting " + description);
                 // We only send L3-encapped broadcasts in DhcpRebindingState,
@@ -928,9 +927,9 @@
         private void logTimeToBoundState() {
             long now = SystemClock.elapsedRealtime();
             if (mLastBoundExitTime > mLastInitEnterTime) {
-                logState(DhcpClientEvent.RENEWING_BOUND, (int)(now - mLastBoundExitTime));
+                logState(EVENT_RENEWING_BOUND, (int) (now - mLastBoundExitTime));
             } else {
-                logState(DhcpClientEvent.INITIAL_BOUND, (int)(now - mLastInitEnterTime));
+                logState(EVENT_INITIAL_BOUND, (int) (now - mLastInitEnterTime));
             }
         }
     }
@@ -1021,7 +1020,7 @@
 
             // We need to broadcast and possibly reconnect the socket to a
             // completely different server.
-            closeQuietly(mUdpSock);
+            closeSocketQuietly(mUdpSock);
             if (!initUdpSocket()) {
                 Log.e(TAG, "Failed to recreate UDP socket");
                 transitionTo(mDhcpInitState);
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java b/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
index eac8d2a..96d1a28 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
@@ -64,7 +64,7 @@
     @Override
     protected int readPacket(@NonNull FileDescriptor fd, @NonNull Payload packetBuffer)
             throws Exception {
-        final InetSocketAddress addr = new InetSocketAddress();
+        final InetSocketAddress addr = new InetSocketAddress(0);
         final int read = Os.recvfrom(
                 fd, packetBuffer.mBytes, 0, packetBuffer.mBytes.length, 0 /* flags */, addr);
 
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
index beabd3e..cd993e9 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
@@ -28,6 +28,7 @@
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.IPPROTO_UDP;
 import static android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOCK_NONBLOCK;
 import static android.system.OsConstants.SOL_SOCKET;
 import static android.system.OsConstants.SO_BROADCAST;
 import static android.system.OsConstants.SO_REUSEADDR;
@@ -43,7 +44,6 @@
 import android.annotation.Nullable;
 import android.net.INetworkStackStatusCallback;
 import android.net.MacAddress;
-import android.net.NetworkUtils;
 import android.net.TrafficStats;
 import android.net.util.SharedLog;
 import android.net.util.SocketUtils;
@@ -207,7 +207,7 @@
         @Override
         public void addArpEntry(@NonNull Inet4Address ipv4Addr, @NonNull MacAddress ethAddr,
                 @NonNull String ifname, @NonNull FileDescriptor fd) throws IOException {
-            NetworkUtils.addArpEntry(ipv4Addr, ethAddr, ifname, fd);
+            SocketUtils.addArpEntry(ipv4Addr, ethAddr, ifname, fd);
         }
 
         @Override
@@ -630,7 +630,7 @@
             // TODO: have and use an API to set a socket tag without going through the thread tag
             final int oldTag = TrafficStats.getAndSetThreadStatsTag(TAG_SYSTEM_DHCP_SERVER);
             try {
-                mSocket = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+                mSocket = Os.socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
                 SocketUtils.bindSocketToInterface(mSocket, mIfName);
                 Os.setsockoptInt(mSocket, SOL_SOCKET, SO_REUSEADDR, 1);
                 Os.setsockoptInt(mSocket, SOL_SOCKET, SO_BROADCAST, 1);
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpServingParams.java b/packages/NetworkStack/src/android/net/dhcp/DhcpServingParams.java
index 31ce95b..3cd2aa4 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpServingParams.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpServingParams.java
@@ -209,7 +209,7 @@
          * but it must always be set explicitly before building the {@link DhcpServingParams}.
          */
         public Builder setDefaultRouters(@NonNull Inet4Address... defaultRouters) {
-            return setDefaultRouters(new ArraySet<>(Arrays.asList(defaultRouters)));
+            return setDefaultRouters(makeArraySet(defaultRouters));
         }
 
         /**
@@ -239,7 +239,7 @@
          * building the {@link DhcpServingParams}.
          */
         public Builder setDnsServers(@NonNull Inet4Address... dnsServers) {
-            return setDnsServers(new ArraySet<>(Arrays.asList(dnsServers)));
+            return setDnsServers(makeArraySet(dnsServers));
         }
 
         /**
@@ -269,7 +269,7 @@
          * and do not need to be set here.
          */
         public Builder setExcludedAddrs(@NonNull Inet4Address... excludedAddrs) {
-            return setExcludedAddrs(new ArraySet<>(Arrays.asList(excludedAddrs)));
+            return setExcludedAddrs(makeArraySet(excludedAddrs));
         }
 
         /**
@@ -368,4 +368,10 @@
     static IpPrefix makeIpPrefix(@NonNull LinkAddress addr) {
         return new IpPrefix(addr.getAddress(), addr.getPrefixLength());
     }
+
+    private static <T> ArraySet<T> makeArraySet(T[] elements) {
+        final ArraySet<T> set = new ArraySet<>(elements.length);
+        set.addAll(Arrays.asList(elements));
+        return set;
+    }
 }
diff --git a/packages/NetworkStack/src/android/net/ip/ConnectivityPacketTracker.java b/packages/NetworkStack/src/android/net/ip/ConnectivityPacketTracker.java
index 385dd52..649257a 100644
--- a/packages/NetworkStack/src/android/net/ip/ConnectivityPacketTracker.java
+++ b/packages/NetworkStack/src/android/net/ip/ConnectivityPacketTracker.java
@@ -20,12 +20,13 @@
 import static android.system.OsConstants.AF_PACKET;
 import static android.system.OsConstants.ARPHRD_ETHER;
 import static android.system.OsConstants.ETH_P_ALL;
+import static android.system.OsConstants.SOCK_NONBLOCK;
 import static android.system.OsConstants.SOCK_RAW;
 
-import android.net.NetworkUtils;
 import android.net.util.ConnectivityPacketSummary;
 import android.net.util.InterfaceParams;
 import android.net.util.PacketReader;
+import android.net.util.SocketUtils;
 import android.os.Handler;
 import android.system.ErrnoException;
 import android.system.Os;
@@ -33,7 +34,7 @@
 import android.util.LocalLog;
 import android.util.Log;
 
-import libcore.util.HexEncoding;
+import com.android.internal.util.HexDump;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -101,9 +102,10 @@
         protected FileDescriptor createFd() {
             FileDescriptor s = null;
             try {
-                s = Os.socket(AF_PACKET, SOCK_RAW, 0);
-                NetworkUtils.attachControlPacketFilter(s, ARPHRD_ETHER);
-                Os.bind(s, makePacketSocketAddress((short) ETH_P_ALL, mInterface.index));
+                s = Os.socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, 0);
+                SocketUtils.attachControlPacketFilter(s, ARPHRD_ETHER);
+                SocketUtils.bindSocket(
+                        s, makePacketSocketAddress((short) ETH_P_ALL, mInterface.index));
             } catch (ErrnoException | IOException e) {
                 logError("Failed to create packet tracking socket: ", e);
                 closeFd(s);
@@ -119,8 +121,7 @@
             if (summary == null) return;
 
             if (DBG) Log.d(mTag, summary);
-            addLogEntry(summary +
-                        "\n[" + new String(HexEncoding.encode(recvbuf, 0, length)) + "]");
+            addLogEntry(summary + "\n[" + HexDump.toHexString(recvbuf, 0, length) + "]");
         }
 
         @Override
diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java
index 4315d34..12fe8c5 100644
--- a/packages/NetworkStack/src/android/net/ip/IpClient.java
+++ b/packages/NetworkStack/src/android/net/ip/IpClient.java
@@ -16,6 +16,7 @@
 
 package android.net.ip;
 
+import static android.net.RouteInfo.RTN_UNICAST;
 import static android.net.shared.IpConfigurationParcelableUtil.toStableParcelable;
 import static android.net.shared.LinkPropertiesParcelableUtil.fromStableParcelable;
 import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable;
@@ -36,7 +37,6 @@
 import android.net.apf.ApfCapabilities;
 import android.net.apf.ApfFilter;
 import android.net.dhcp.DhcpClient;
-import android.net.ip.IIpClientCallbacks;
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.IpManagerEvent;
 import android.net.shared.InitialConfiguration;
@@ -52,7 +52,6 @@
 import android.util.Log;
 import android.util.SparseArray;
 
-import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IState;
 import com.android.internal.util.IndentingPrintWriter;
@@ -992,7 +991,7 @@
             // specified in the InitialConfiguration have been observed with Netlink.
             if (config.isProvisionedBy(newLp.getLinkAddresses(), null)) {
                 for (IpPrefix prefix : config.directlyConnectedRoutes) {
-                    newLp.addRoute(new RouteInfo(prefix, null, mInterfaceName));
+                    newLp.addRoute(new RouteInfo(prefix, null, mInterfaceName, RTN_UNICAST));
                 }
             }
             addAllReachableDnsServers(newLp, config.dnsServers);
@@ -1093,7 +1092,7 @@
         // If we have a StaticIpConfiguration attempt to apply it and
         // handle the result accordingly.
         if (mConfiguration.mStaticIpConfig != null) {
-            if (mInterfaceCtrl.setIPv4Address(mConfiguration.mStaticIpConfig.ipAddress)) {
+            if (mInterfaceCtrl.setIPv4Address(mConfiguration.mStaticIpConfig.getIpAddress())) {
                 handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
             } else {
                 return false;
@@ -1348,10 +1347,8 @@
             apfConfig.apfCapabilities = mConfiguration.mApfCapabilities;
             apfConfig.multicastFilter = mMulticastFiltering;
             // Get the Configuration for ApfFilter from Context
-            apfConfig.ieee802_3Filter =
-                    mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);
-            apfConfig.ethTypeBlackList =
-                    mContext.getResources().getIntArray(R.array.config_apfEthTypeBlackList);
+            apfConfig.ieee802_3Filter = ApfCapabilities.getApfDrop8023Frames(mContext);
+            apfConfig.ethTypeBlackList = ApfCapabilities.getApfEthTypeBlackList(mContext);
             mApfFilter = ApfFilter.maybeCreate(mContext, apfConfig, mInterfaceParams, mCallback);
             // TODO: investigate the effects of any multicast filtering racing/interfering with the
             // rest of this IP configuration startup.
diff --git a/packages/NetworkStack/src/android/net/ip/IpNeighborMonitor.java b/packages/NetworkStack/src/android/net/ip/IpNeighborMonitor.java
index 2e6ff24..b29d617 100644
--- a/packages/NetworkStack/src/android/net/ip/IpNeighborMonitor.java
+++ b/packages/NetworkStack/src/android/net/ip/IpNeighborMonitor.java
@@ -20,6 +20,10 @@
 import static android.net.netlink.NetlinkConstants.hexify;
 import static android.net.netlink.NetlinkConstants.stringForNlMsgType;
 import static android.net.util.SocketUtils.makeNetlinkSocketAddress;
+import static android.system.OsConstants.AF_NETLINK;
+import static android.system.OsConstants.NETLINK_ROUTE;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOCK_NONBLOCK;
 
 import android.net.MacAddress;
 import android.net.netlink.NetlinkErrorMessage;
@@ -27,8 +31,10 @@
 import android.net.netlink.NetlinkSocket;
 import android.net.netlink.RtNetlinkNeighborMessage;
 import android.net.netlink.StructNdMsg;
+import android.net.util.NetworkStackUtils;
 import android.net.util.PacketReader;
 import android.net.util.SharedLog;
+import android.net.util.SocketUtils;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.system.ErrnoException;
@@ -36,8 +42,6 @@
 import android.system.OsConstants;
 import android.util.Log;
 
-import libcore.io.IoUtils;
-
 import java.io.FileDescriptor;
 import java.net.InetAddress;
 import java.net.SocketAddress;
@@ -77,7 +81,7 @@
                 1, ip, StructNdMsg.NUD_PROBE, ifIndex, null);
 
         try {
-            NetlinkSocket.sendOneShotKernelMessage(OsConstants.NETLINK_ROUTE, msg);
+            NetlinkSocket.sendOneShotKernelMessage(NETLINK_ROUTE, msg);
         } catch (ErrnoException e) {
             Log.e(TAG, "Error " + msgSnippet + ": " + e);
             return -e.errno;
@@ -145,8 +149,8 @@
         FileDescriptor fd = null;
 
         try {
-            fd = NetlinkSocket.forProto(OsConstants.NETLINK_ROUTE);
-            Os.bind(fd, makeNetlinkSocketAddress(0, OsConstants.RTMGRP_NEIGH));
+            fd = Os.socket(AF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, NETLINK_ROUTE);
+            SocketUtils.bindSocket(fd, makeNetlinkSocketAddress(0, OsConstants.RTMGRP_NEIGH));
             NetlinkSocket.connectToKernel(fd);
 
             if (VDBG) {
@@ -155,7 +159,7 @@
             }
         } catch (ErrnoException|SocketException e) {
             logError("Failed to create rtnetlink socket", e);
-            IoUtils.closeQuietly(fd);
+            NetworkStackUtils.closeSocketQuietly(fd);
             return null;
         }
 
diff --git a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
index 6dcf0c0..98123a5 100644
--- a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
+++ b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
@@ -16,6 +16,9 @@
 
 package android.net.util;
 
+import java.io.FileDescriptor;
+import java.io.IOException;
+
 /**
  * Collection of utilities for the network stack.
  */
@@ -27,4 +30,14 @@
     public static <T> boolean isEmpty(T[] array) {
         return array == null || array.length == 0;
     }
+
+    /**
+     * Close a socket, ignoring any exception while closing.
+     */
+    public static void closeSocketQuietly(FileDescriptor fd) {
+        try {
+            SocketUtils.closeSocket(fd);
+        } catch (IOException ignored) {
+        }
+    }
 }
diff --git a/packages/NetworkStack/src/com/android/server/NetworkObserverRegistry.java b/packages/NetworkStack/src/com/android/server/NetworkObserverRegistry.java
index 4f55779..6fb4b0d 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkObserverRegistry.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkObserverRegistry.java
@@ -15,6 +15,8 @@
  */
 package com.android.server;
 
+import static android.net.RouteInfo.RTN_UNICAST;
+
 import android.annotation.NonNull;
 import android.net.INetd;
 import android.net.INetdUnsolicitedEventListener;
@@ -169,7 +171,7 @@
     public void onRouteChanged(boolean updated, String route, String gateway, String ifName) {
         final RouteInfo processRoute = new RouteInfo(new IpPrefix(route),
                 ("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway),
-                ifName);
+                ifName, RTN_UNICAST);
         if (updated) {
             invokeForAllObservers(o -> o.onRouteUpdated(processRoute));
         } else {
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index 7405c47..cedcb84 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -19,6 +19,7 @@
 import static android.net.dhcp.IDhcpServer.STATUS_INVALID_ARGUMENT;
 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
 import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR;
+import static android.net.shared.NetworkParcelableUtil.fromStableParcelable;
 
 import static com.android.server.util.PermissionUtil.checkDumpPermission;
 import static com.android.server.util.PermissionUtil.checkNetworkStackCallingPermission;
@@ -34,7 +35,7 @@
 import android.net.INetworkMonitorCallbacks;
 import android.net.INetworkStackConnector;
 import android.net.Network;
-import android.net.NetworkRequest;
+import android.net.NetworkParcelable;
 import android.net.PrivateDnsConfigParcel;
 import android.net.dhcp.DhcpServer;
 import android.net.dhcp.DhcpServingParams;
@@ -150,13 +151,12 @@
         }
 
         @Override
-        public void makeNetworkMonitor(int netId, String name, INetworkMonitorCallbacks cb)
+        public void makeNetworkMonitor(
+                NetworkParcelable network, String name, INetworkMonitorCallbacks cb)
                 throws RemoteException {
-            final Network network = new Network(netId, false /* privateDnsBypass */);
-            final NetworkRequest defaultRequest = mCm.getDefaultRequest();
-            final SharedLog log = addValidationLogs(network, name);
-            final NetworkMonitor nm = new NetworkMonitor(
-                    mContext, cb, network, defaultRequest, log);
+            final Network parsedNetwork = fromStableParcelable(network);
+            final SharedLog log = addValidationLogs(parsedNetwork, name);
+            final NetworkMonitor nm = new NetworkMonitor(mContext, cb, parsedNetwork, log);
             cb.onNetworkMonitorCreated(new NetworkMonitorImpl(nm));
         }
 
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index 96eaa50..dbffa6d 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -47,7 +47,6 @@
 import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
 import android.net.ProxyInfo;
 import android.net.TrafficStats;
 import android.net.Uri;
@@ -110,6 +109,8 @@
     private static final boolean DBG  = true;
     private static final boolean VDBG = false;
     private static final boolean VDBG_STALL = Log.isLoggable(TAG, Log.DEBUG);
+    // TODO: use another permission for CaptivePortalLoginActivity once it has its own certificate
+    private static final String PERMISSION_NETWORK_SETTINGS = "android.permission.NETWORK_SETTINGS";
     // Default configuration values for captive portal detection probes.
     // TODO: append a random length parameter to the default HTTPS url.
     // TODO: randomize browser version ids in the default User-Agent String.
@@ -310,14 +311,14 @@
     private long mLastProbeTime;
 
     public NetworkMonitor(Context context, INetworkMonitorCallbacks cb, Network network,
-            NetworkRequest defaultRequest, SharedLog validationLog) {
-        this(context, cb, network, defaultRequest, new IpConnectivityLog(), validationLog,
+            SharedLog validationLog) {
+        this(context, cb, network, new IpConnectivityLog(), validationLog,
                 Dependencies.DEFAULT);
     }
 
     @VisibleForTesting
     protected NetworkMonitor(Context context, INetworkMonitorCallbacks cb, Network network,
-            NetworkRequest defaultRequest, IpConnectivityLog logger, SharedLog validationLogs,
+            IpConnectivityLog logger, SharedLog validationLogs,
             Dependencies deps) {
         // Add suffix indicating which NetworkMonitor we're talking about.
         super(TAG + "/" + network.toString());
@@ -369,8 +370,7 @@
         // we can ever fetch them.
         // TODO: Delete ASAP.
         mLinkProperties = new LinkProperties();
-        mNetworkCapabilities = new NetworkCapabilities();
-        mNetworkCapabilities.clearAll();
+        mNetworkCapabilities = new NetworkCapabilities(null);
     }
 
     /**
@@ -684,11 +684,20 @@
                                 public void appResponse(int response) {
                                     if (response == APP_RETURN_WANTED_AS_IS) {
                                         mContext.enforceCallingPermission(
-                                                android.Manifest.permission.CONNECTIVITY_INTERNAL,
+                                                PERMISSION_NETWORK_SETTINGS,
                                                 "CaptivePortal");
                                     }
                                     sendMessage(CMD_CAPTIVE_PORTAL_APP_FINISHED, response);
                                 }
+
+                                @Override
+                                public void logEvent(int eventId, String packageName)
+                                        throws RemoteException {
+                                    mContext.enforceCallingPermission(
+                                            PERMISSION_NETWORK_SETTINGS,
+                                            "CaptivePortal");
+                                    mCallback.logCaptivePortalLoginEvent(eventId, packageName);
+                                }
                             }));
                     final CaptivePortalProbeResult probeRes = mLastPortalProbeResult;
                     intent.putExtra(EXTRA_CAPTIVE_PORTAL_URL, probeRes.detectUrl);
diff --git a/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java b/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
index 82bf038..f6eb900 100644
--- a/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
+++ b/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
@@ -19,6 +19,7 @@
 import static android.os.Binder.getCallingUid;
 
 import android.os.Process;
+import android.os.UserHandle;
 
 /**
  * Utility class to check calling permissions on the network stack.
@@ -32,7 +33,7 @@
     public static void checkNetworkStackCallingPermission() {
         // TODO: check that the calling PID is the system server.
         final int caller = getCallingUid();
-        if (caller != Process.SYSTEM_UID && caller != Process.BLUETOOTH_UID) {
+        if (caller != Process.SYSTEM_UID && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID) {
             throw new SecurityException("Invalid caller: " + caller);
         }
     }
diff --git a/packages/NetworkStack/tests/src/android/net/util/PacketReaderTest.java b/packages/NetworkStack/tests/src/android/net/util/PacketReaderTest.java
index dced743..6e11c40 100644
--- a/packages/NetworkStack/tests/src/android/net/util/PacketReaderTest.java
+++ b/packages/NetworkStack/tests/src/android/net/util/PacketReaderTest.java
@@ -17,7 +17,13 @@
 package android.net.util;
 
 import static android.net.util.PacketReader.DEFAULT_RECV_BUF_SIZE;
-import static android.system.OsConstants.*;
+import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.IPPROTO_UDP;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOCK_NONBLOCK;
+import static android.system.OsConstants.SOL_SOCKET;
+import static android.system.OsConstants.SO_SNDTIMEO;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -31,10 +37,12 @@
 import android.system.Os;
 import android.system.StructTimeval;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.UncheckedIOException;
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.Inet6Address;
@@ -45,13 +53,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-import org.junit.runner.RunWith;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import libcore.io.IoBridge;
-
 /**
  * Tests for PacketReader.
  *
@@ -80,7 +81,7 @@
         protected FileDescriptor createFd() {
             FileDescriptor s = null;
             try {
-                s = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+                s = Os.socket(AF_INET6, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
                 Os.bind(s, LOOPBACK6, 0);
                 mLocalSockName = (InetSocketAddress) Os.getsockname(s);
                 Os.setsockoptTimeval(s, SOL_SOCKET, SO_SNDTIMEO, TIMEO);
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index d31fa77..d11bb64 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -21,7 +21,6 @@
 import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
 import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
@@ -51,7 +50,6 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
-import android.net.NetworkRequest;
 import android.net.captiveportal.CaptivePortalProbeResult;
 import android.net.metrics.IpConnectivityLog;
 import android.net.util.SharedLog;
@@ -103,7 +101,6 @@
     private @Mock NetworkMonitor.Dependencies mDependencies;
     private @Mock INetworkMonitorCallbacks mCallbacks;
     private @Spy Network mNetwork = new Network(TEST_NETID);
-    private NetworkRequest mRequest;
 
     private static final int TEST_NETID = 4242;
 
@@ -178,10 +175,6 @@
                 InetAddresses.parseNumericAddress("192.168.0.0")
         }).when(mNetwork).getAllByName(any());
 
-        mRequest = new NetworkRequest.Builder()
-                .addCapability(NET_CAPABILITY_INTERNET)
-                .addCapability(NET_CAPABILITY_NOT_RESTRICTED)
-                .build();
         // Default values. Individual tests can override these.
         when(mCm.getLinkProperties(any())).thenReturn(TEST_LINKPROPERTIES);
         when(mCm.getNetworkCapabilities(any())).thenReturn(METERED_CAPABILITIES);
@@ -195,9 +188,9 @@
     private class WrappedNetworkMonitor extends NetworkMonitor {
         private long mProbeTime = 0;
 
-        WrappedNetworkMonitor(Context context, Network network, NetworkRequest defaultRequest,
-                IpConnectivityLog logger, Dependencies deps) {
-                super(context, mCallbacks, network, defaultRequest, logger,
+        WrappedNetworkMonitor(Context context, Network network, IpConnectivityLog logger,
+                Dependencies deps) {
+                super(context, mCallbacks, network, logger,
                         new SharedLog("test_nm"), deps);
         }
 
@@ -213,7 +206,7 @@
 
     private WrappedNetworkMonitor makeMeteredWrappedNetworkMonitor() {
         final WrappedNetworkMonitor nm = new WrappedNetworkMonitor(
-                mContext, mNetwork, mRequest, mLogger, mDependencies);
+                mContext, mNetwork, mLogger, mDependencies);
         when(mCm.getNetworkCapabilities(any())).thenReturn(METERED_CAPABILITIES);
         nm.start();
         waitForIdle(nm.getHandler());
@@ -222,7 +215,7 @@
 
     private WrappedNetworkMonitor makeNotMeteredWrappedNetworkMonitor() {
         final WrappedNetworkMonitor nm = new WrappedNetworkMonitor(
-                mContext, mNetwork, mRequest, mLogger, mDependencies);
+                mContext, mNetwork, mLogger, mDependencies);
         when(mCm.getNetworkCapabilities(any())).thenReturn(NOT_METERED_CAPABILITIES);
         nm.start();
         waitForIdle(nm.getHandler());
@@ -231,7 +224,7 @@
 
     private NetworkMonitor makeMonitor() {
         final NetworkMonitor nm = new NetworkMonitor(
-                mContext, mCallbacks, mNetwork, mRequest, mLogger, mValidationLogger,
+                mContext, mCallbacks, mNetwork, mLogger, mValidationLogger,
                 mDependencies);
         nm.start();
         waitForIdle(nm.getHandler());
diff --git a/packages/NetworkStackPermissionStub/Android.bp b/packages/NetworkStackPermissionStub/Android.bp
new file mode 100644
index 0000000..94870c9
--- /dev/null
+++ b/packages/NetworkStackPermissionStub/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Stub APK to define permissions for NetworkStack
+android_app {
+    name: "NetworkStackPermissionStub",
+    // TODO: mark app as hasCode=false in manifest once soong stops complaining about apps without
+    // a classes.dex.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+    privileged: true,
+    manifest: "AndroidManifest.xml",
+}
diff --git a/packages/NetworkStackPermissionStub/AndroidManifest.xml b/packages/NetworkStackPermissionStub/AndroidManifest.xml
new file mode 100644
index 0000000..2ccf5ff
--- /dev/null
+++ b/packages/NetworkStackPermissionStub/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.mainline.networkstack.permissionstub">
+    <!--
+    This package only exists to define the below permissions, and enforce that they are only
+    granted to apps sharing the same signature.
+    Permissions defined here are intended to be used only by the NetworkStack: both
+    NetworkStack and this stub APK are to be signed with a dedicated certificate to ensure
+    that, with the below permissions being signature permissions.
+
+    This APK *must* be installed, even if the NetworkStack app is not installed, because otherwise,
+    any application will be able to define this permission and the system will give that application
+    full access to the network stack.
+     -->
+    <permission android:name="android.permission.MAINLINE_NETWORK_STACK"
+                android:protectionLevel="signature"/>
+
+    <application android:name="com.android.server.NetworkStackPermissionStub"/>
+</manifest>
\ No newline at end of file
diff --git a/packages/NetworkStackPermissionStub/src/com/android/server/NetworkStackPermissionStub.java b/packages/NetworkStackPermissionStub/src/com/android/server/NetworkStackPermissionStub.java
new file mode 100644
index 0000000..01e59d2
--- /dev/null
+++ b/packages/NetworkStackPermissionStub/src/com/android/server/NetworkStackPermissionStub.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.app.Application;
+
+/**
+ * Empty application for NetworkStackStub that only exists because soong builds complain if APKs
+ * have no source file.
+ */
+public class NetworkStackPermissionStub extends Application {
+}
diff --git a/packages/SettingsLib/OWNERS b/packages/SettingsLib/OWNERS
index d188c65..d879087 100644
--- a/packages/SettingsLib/OWNERS
+++ b/packages/SettingsLib/OWNERS
@@ -4,7 +4,7 @@
 dehboxturtle@google.com
 dhnishi@google.com
 dling@google.com
-dsandler@google.com
+dsandler@android.com
 evanlaird@google.com
 jackqdyulei@google.com
 jmonk@google.com
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index 2a3cf3e..3f6ebf0 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -1,6 +1,6 @@
 set noparent
 
-dsandler@google.com
+dsandler@android.com
 
 adamcohen@google.com
 asc@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
old mode 100755
new mode 100644
index 8450b74..7a64f5a
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -35,6 +35,7 @@
 import android.os.Debug;
 import android.os.Handler;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
@@ -242,7 +243,8 @@
         ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
-        mContext.registerReceiver(mBroadcastReceiver, intentFilter);
+        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, intentFilter,
+                null, null);
 
         if (sSettingsPackageAndClassNamePairList == null) {
             String[] settings = mContext.getResources().getStringArray(
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index 8172e71..1d0b9b6 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -20,6 +20,7 @@
         package="com.android.vpndialogs">
 
     <uses-permission android:name="android.permission.CONTROL_VPN" />
+    <uses-permission android:name="android.permission.CONTROL_ALWAYS_ON_VPN" />
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
 
     <application android:label="VpnDialogs"
diff --git a/proto/Android.bp b/proto/Android.bp
index f3811bd..9b7a1c1 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -17,3 +17,24 @@
         },
     },
 }
+
+java_library_static {
+    name: "metrics-constants-protos",
+    host_supported: true,
+    proto: {
+        type: "nano",
+    },
+    srcs: ["src/metrics_constants.proto"],
+    no_framework_libs: true,
+    sdk_version: "system_current",
+    // Pin java_version until jarjar is certified to support later versions. http://b/72703434
+    java_version: "1.8",
+    target: {
+        android: {
+            jarjar_rules: "jarjar-rules.txt",
+        },
+        host: {
+            static_libs: ["libprotobuf-java-nano"],
+        },
+    },
+}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 9b8f51e..48b69b0 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -7,6 +7,7 @@
             "frameworks/native/cmds/dumpstate/binder",
             "system/core/storaged/binder",
             "system/vold/binder",
+            "system/gsid/aidl",
         ],
     },
     srcs: [
@@ -15,6 +16,7 @@
         ":installd_aidl",
         ":storaged_aidl",
         ":vold_aidl",
+        ":gsiservice_aidl",
         ":mediaupdateservice_aidl",
         "java/com/android/server/EventLogTags.logtags",
         "java/com/android/server/am/EventLogTags.logtags",
@@ -45,7 +47,7 @@
         "android.hardware.vibrator-V1.0-java",
         "android.hardware.configstore-V1.0-java",
         "android.hardware.contexthub-V1.0-java",
-        "android.hidl.manager-V1.0-java",
+        "android.hidl.manager-V1.2-java",
         "netd_aidl_interface-java",
         "netd_event_listener_interface-java",
     ],
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 1519c17..08e4903 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -40,6 +40,7 @@
 import static android.net.NetworkPolicyManager.uidRulesToString;
 import static android.net.NetworkStack.NETWORKSTACK_PACKAGE_NAME;
 import static android.net.shared.NetworkMonitorUtils.isValidationRequired;
+import static android.net.shared.NetworkParcelableUtil.toStableParcelable;
 import static android.os.Process.INVALID_UID;
 import static android.system.OsConstants.IPPROTO_TCP;
 import static android.system.OsConstants.IPPROTO_UDP;
@@ -98,10 +99,10 @@
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.NetworkEvent;
 import android.net.netlink.InetDiagMessage;
-import android.net.shared.NetdService;
 import android.net.shared.NetworkMonitorUtils;
 import android.net.shared.PrivateDnsConfig;
 import android.net.util.MultinetworkPolicyTracker;
+import android.net.util.NetdService;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -144,6 +145,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.net.LegacyVpnInfo;
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnInfo;
@@ -2683,6 +2685,11 @@
                     EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE,
                     mNai.network.netId));
         }
+
+        @Override
+        public void logCaptivePortalLoginEvent(int eventId, String packageName) {
+            new MetricsLogger().action(eventId, packageName);
+        }
     }
 
     private boolean networkRequiresValidation(NetworkAgentInfo nai) {
@@ -3636,6 +3643,20 @@
         mTethering.stopTethering(type);
     }
 
+    /**
+     * Get the latest value of the tethering entitlement check.
+     *
+     * Note: Allow privileged apps who have TETHER_PRIVILEGED permission to access. If it turns
+     * out some such apps are observed to abuse this API, change to per-UID limits on this API
+     * if it's really needed.
+     */
+    @Override
+    public void getLatestTetheringEntitlementValue(int type, ResultReceiver receiver,
+            boolean showEntitlementUi, String callerPkg) {
+        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
+        mTethering.getLatestTetheringEntitlementValue(type, receiver, showEntitlementUi);
+    }
+
     // Called when we lose the default network and have no replacement yet.
     // This will automatically be cleared after X seconds or a new default network
     // becomes CONNECTED, whichever happens first.  The timer is started by the
@@ -5012,8 +5033,8 @@
         if (DBG) log("registerNetworkAgent " + nai);
         final long token = Binder.clearCallingIdentity();
         try {
-            mContext.getSystemService(NetworkStack.class)
-                    .makeNetworkMonitor(nai.network, name, new NetworkMonitorCallbacks(nai));
+            mContext.getSystemService(NetworkStack.class).makeNetworkMonitor(
+                    toStableParcelable(nai.network), name, new NetworkMonitorCallbacks(nai));
         } finally {
             Binder.restoreCallingIdentity(token);
         }
diff --git a/services/core/java/com/android/server/DynamicAndroidService.java b/services/core/java/com/android/server/DynamicAndroidService.java
new file mode 100644
index 0000000..12a3f02
--- /dev/null
+++ b/services/core/java/com/android/server/DynamicAndroidService.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.gsi.GsiProgress;
+import android.gsi.IGsiService;
+import android.os.IBinder;
+import android.os.IBinder.DeathRecipient;
+import android.os.IDynamicAndroidService;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+
+/**
+ * DynamicAndroidService implements IDynamicAndroidService. It provides permission check before
+ * passing requests to gsid
+ */
+public class DynamicAndroidService extends IDynamicAndroidService.Stub implements DeathRecipient {
+    private static final String TAG = "DynamicAndroidService";
+    private static final String NO_SERVICE_ERROR = "no gsiservice";
+
+    private Context mContext;
+    private volatile IGsiService mGsiService;
+
+    DynamicAndroidService(Context context) {
+        mContext = context;
+    }
+
+    private static IGsiService connect(DeathRecipient recipient) throws RemoteException {
+        IBinder binder = ServiceManager.getService("gsiservice");
+        if (binder == null) {
+            throw new RemoteException(NO_SERVICE_ERROR);
+        }
+        /**
+         * The init will restart gsiservice if it crashed and the proxy object will need to be
+         * re-initialized in this case.
+         */
+        binder.linkToDeath(recipient, 0);
+        return IGsiService.Stub.asInterface(binder);
+    }
+
+    /** implements DeathRecipient */
+    @Override
+    public void binderDied() {
+        Slog.w(TAG, "gsiservice died; reconnecting");
+        synchronized (this) {
+            mGsiService = null;
+        }
+    }
+
+    private IGsiService getGsiService() throws RemoteException {
+        checkPermission();
+        synchronized (this) {
+            if (mGsiService == null) {
+                mGsiService = connect(this);
+            }
+            return mGsiService;
+        }
+    }
+
+    private void checkPermission() {
+        if (mContext.checkCallingOrSelfPermission(
+                        android.Manifest.permission.MANAGE_DYNAMIC_ANDROID)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires MANAGE_DYNAMIC_ANDROID permission");
+        }
+    }
+
+    @Override
+    public boolean startInstallation(long systemSize, long userdataSize) throws RemoteException {
+        return getGsiService().startGsiInstall(systemSize, userdataSize, true) == 0;
+    }
+
+    @Override
+    public GsiProgress getInstallationProgress() throws RemoteException {
+        return getGsiService().getInstallProgress();
+    }
+
+    @Override
+    public boolean abort() throws RemoteException {
+        return getGsiService().cancelGsiInstall();
+    }
+
+    @Override
+    public boolean isInUse() throws RemoteException {
+        return getGsiService().isGsiRunning();
+    }
+
+    @Override
+    public boolean isInstalled() throws RemoteException {
+        return getGsiService().isGsiInstalled();
+    }
+
+    @Override
+    public boolean remove() throws RemoteException {
+        return getGsiService().removeGsiInstall();
+    }
+
+    @Override
+    public boolean toggle() throws RemoteException {
+        IGsiService gsiService = getGsiService();
+        if (gsiService.isGsiRunning()) {
+            return gsiService.disableGsiInstall();
+        } else {
+            return gsiService.setGsiBootable() == 0;
+        }
+    }
+
+    @Override
+    public boolean write(byte[] buf) throws RemoteException {
+        return getGsiService().commitGsiChunkFromMemory(buf);
+    }
+
+    @Override
+    public boolean commit() throws RemoteException {
+        return getGsiService().setGsiBootable() == 0;
+    }
+}
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 371276f..126bf65 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -44,7 +44,7 @@
 import android.net.Network;
 import android.net.NetworkUtils;
 import android.net.TrafficStats;
-import android.net.shared.NetdService;
+import android.net.util.NetdService;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 8592491..da4df22 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -62,7 +62,7 @@
 import android.net.RouteInfo;
 import android.net.TetherStatsParcel;
 import android.net.UidRange;
-import android.net.shared.NetdService;
+import android.net.util.NetdService;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Handler;
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index cbfcd60..43af36f 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -52,6 +52,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting;
 import android.telephony.emergency.EmergencyNumber;
+import android.telephony.ims.ImsReasonInfo;
 import android.util.LocalLog;
 import android.util.StatsLog;
 
@@ -227,6 +228,8 @@
 
     private int mCallDisconnectCause = DisconnectCause.NOT_VALID;
 
+    private List<ImsReasonInfo> mImsReasonInfo = null;
+
     private int mCallPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
 
     private boolean mCarrierNetworkChangeState = false;
@@ -377,6 +380,7 @@
         mCellLocation = new Bundle[numPhones];
         mCellInfo = new ArrayList<List<CellInfo>>();
         mSrvccState = new int[numPhones];
+        mImsReasonInfo = new ArrayList<ImsReasonInfo>();
         mPhysicalChannelConfigs = new ArrayList<List<PhysicalChannelConfig>>();
         mEmergencyNumberList = new HashMap<>();
         for (int i = 0; i < numPhones; i++) {
@@ -394,6 +398,7 @@
             mCallForwarding[i] =  false;
             mCellLocation[i] = new Bundle();
             mCellInfo.add(i, null);
+            mImsReasonInfo.add(i, null);
             mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
             mPhysicalChannelConfigs.add(i, new ArrayList<PhysicalChannelConfig>());
         }
@@ -739,6 +744,13 @@
                             remove(r.binder);
                         }
                     }
+                    if ((events & PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES) != 0) {
+                        try {
+                            r.callback.onImsCallDisconnectCauseChanged(mImsReasonInfo.get(phoneId));
+                        } catch (RemoteException ex) {
+                            remove(r.binder);
+                        }
+                    }
                     if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
                         try {
                             r.callback.onPreciseDataConnectionStateChanged(
@@ -1591,6 +1603,34 @@
         }
     }
 
+    public void notifyImsDisconnectCause(int subId, ImsReasonInfo imsReasonInfo) {
+        if (!checkNotifyPermission("notifyImsCallDisconnectCause()")) {
+            return;
+        }
+        int phoneId = SubscriptionManager.getPhoneId(subId);
+        synchronized (mRecords) {
+            if (validatePhoneId(phoneId)) {
+                mImsReasonInfo.set(phoneId, imsReasonInfo);
+                for (Record r : mRecords) {
+                    if (r.matchPhoneStateListenerEvent(
+                            PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES)
+                            && idMatch(r.subId, subId, phoneId)) {
+                        try {
+                            if (DBG_LOC) {
+                                log("notifyImsCallDisconnectCause: mImsReasonInfo="
+                                        + imsReasonInfo + " r=" + r);
+                            }
+                            r.callback.onImsCallDisconnectCauseChanged(mImsReasonInfo.get(phoneId));
+                        } catch (RemoteException ex) {
+                            mRemoveList.add(r.binder);
+                        }
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+    }
+
     public void notifyPreciseDataConnectionFailed(String apnType,
             String apn, @DataFailCause.FailCause int failCause) {
         if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) {
@@ -1627,7 +1667,7 @@
         int phoneId = SubscriptionManager.getPhoneId(subId);
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
-                mSrvccState[phoneId]  = state;
+                mSrvccState[phoneId] = state;
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
                             PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) &&
@@ -1838,6 +1878,7 @@
                 pw.println("mDataConnectionState=" + mDataConnectionState[i]);
                 pw.println("mCellLocation=" + mCellLocation[i]);
                 pw.println("mCellInfo=" + mCellInfo.get(i));
+                pw.println("mImsCallDisconnectCause=" + mImsReasonInfo.get(i).toString());
                 pw.decreaseIndent();
             }
             pw.println("mPreciseDataConnectionState=" + mPreciseDataConnectionState);
@@ -2127,6 +2168,11 @@
                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
         }
 
+        if ((events & PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES) != 0) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
+        }
+
         return true;
     }
 
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index eb5be77..a14fd17 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -121,7 +121,6 @@
 import java.util.HashSet;
 import java.util.Set;
 
-
 /**
  * @hide
  *
@@ -223,7 +222,8 @@
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(ACTION_CARRIER_CONFIG_CHANGED);
-        mEntitlementMgr = mDeps.getEntitlementManager(mContext, mLog, systemProperties);
+        mEntitlementMgr = mDeps.getEntitlementManager(mContext, mTetherMasterSM,
+                mLog, systemProperties);
         mCarrierConfigChange = new VersionedBroadcastListener(
                 "CarrierConfigChangeListener", mContext, smHandler, filter,
                 (Intent ignored) -> {
@@ -470,6 +470,7 @@
                 } else {
                     sendTetherResult(receiver, resultCode);
                 }
+                mEntitlementMgr.updateEntitlementCacheValue(type, resultCode);
             }
         };
 
@@ -1662,6 +1663,14 @@
         mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest());
     }
 
+    /** Get the latest value of the tethering entitlement check. */
+    public void getLatestTetheringEntitlementValue(int type, ResultReceiver receiver,
+            boolean showEntitlementUi) {
+        if (receiver != null) {
+            mEntitlementMgr.getLatestTetheringEntitlementValue(type, receiver, showEntitlementUi);
+        }
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         // Binder.java closes the resource for us.
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 2508844..9141ccb 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -165,6 +165,7 @@
     private final NetworkInfo mNetworkInfo;
     private String mPackage;
     private int mOwnerUID;
+    private boolean mIsPackageTargetingAtLeastQ;
     private String mInterface;
     private Connection mConnection;
     private LegacyVpnRunner mLegacyVpnRunner;
@@ -226,6 +227,7 @@
 
         mPackage = VpnConfig.LEGACY_VPN;
         mOwnerUID = getAppUid(mPackage, mUserHandle);
+        mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(mPackage);
 
         try {
             netService.registerObserver(mObserver);
@@ -267,8 +269,11 @@
 
     public void updateCapabilities() {
         final Network[] underlyingNetworks = (mConfig != null) ? mConfig.underlyingNetworks : null;
+        // Only apps targeting Q and above can explicitly declare themselves as metered.
+        final boolean isAlwaysMetered =
+                mIsPackageTargetingAtLeastQ && (mConfig == null || mConfig.isMetered);
         updateCapabilities(mContext.getSystemService(ConnectivityManager.class), underlyingNetworks,
-                mNetworkCapabilities);
+                mNetworkCapabilities, isAlwaysMetered);
 
         if (mNetworkAgent != null) {
             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
@@ -277,11 +282,13 @@
 
     @VisibleForTesting
     public static void updateCapabilities(ConnectivityManager cm, Network[] underlyingNetworks,
-            NetworkCapabilities caps) {
+            NetworkCapabilities caps, boolean isAlwaysMetered) {
         int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
         int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
         int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
-        boolean metered = false;
+        // VPN's meteredness is OR'd with isAlwaysMetered and meteredness of its underlying
+        // networks.
+        boolean metered = isAlwaysMetered;
         boolean roaming = false;
         boolean congested = false;
 
@@ -724,6 +731,7 @@
             Log.i(TAG, "Switched from " + mPackage + " to " + newPackage);
             mPackage = newPackage;
             mOwnerUID = getAppUid(newPackage, mUserHandle);
+            mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage);
             try {
                 mNetd.allowProtect(mOwnerUID);
             } catch (Exception e) {
@@ -789,6 +797,21 @@
         return result;
     }
 
+    private boolean doesPackageTargetAtLeastQ(String packageName) {
+        if (VpnConfig.LEGACY_VPN.equals(packageName)) {
+            return true;
+        }
+        PackageManager pm = mContext.getPackageManager();
+        try {
+            ApplicationInfo appInfo =
+                    pm.getApplicationInfoAsUser(packageName, 0 /*flags*/, mUserHandle);
+            return appInfo.targetSdkVersion >= VERSION_CODES.Q;
+        } catch (NameNotFoundException unused) {
+            Log.w(TAG, "Can't find \"" + packageName + "\"");
+            return false;
+        }
+    }
+
     public NetworkInfo getNetworkInfo() {
         return mNetworkInfo;
     }
@@ -1076,6 +1099,8 @@
                 // as rules are deleted. This prevents data leakage as the rules are moved over.
                 agentDisconnect(oldNetworkAgent);
             }
+            // Set up VPN's capabilities such as meteredness.
+            updateCapabilities();
 
             if (oldConnection != null) {
                 mContext.unbindService(oldConnection);
@@ -1776,6 +1801,7 @@
         config.user = profile.key;
         config.interfaze = iface;
         config.session = profile.name;
+        config.isMetered = false;
 
         config.addLegacyRoutes(profile.routes);
         if (!profile.dnsServers.isEmpty()) {
diff --git a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java b/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
index a4e3e1d..75aac10 100644
--- a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
+++ b/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
@@ -21,6 +21,9 @@
 import static android.net.ConnectivityManager.EXTRA_REM_TETHER_TYPE;
 import static android.net.ConnectivityManager.EXTRA_RUN_PROVISION;
 import static android.net.ConnectivityManager.EXTRA_SET_ALARM;
+import static android.net.ConnectivityManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
+import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
+import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
 
 import static com.android.internal.R.string.config_wifi_tether_enable;
 
@@ -31,15 +34,21 @@
 import android.content.res.Resources;
 import android.net.util.SharedLog;
 import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Parcel;
 import android.os.PersistableBundle;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
 import android.util.ArraySet;
+import android.util.Log;
+import android.util.SparseIntArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.StateMachine;
 import com.android.server.connectivity.MockableSystemProperties;
 
 /**
@@ -50,6 +59,7 @@
  */
 public class EntitlementManager {
     private static final String TAG = EntitlementManager.class.getSimpleName();
+    private static final boolean DBG = false;
 
     // {@link ComponentName} of the Service used to run tether provisioning.
     private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(
@@ -65,15 +75,19 @@
     private final Context mContext;
     private final MockableSystemProperties mSystemProperties;
     private final SharedLog mLog;
+    private final Handler mMasterHandler;
+    private final SparseIntArray mEntitlementCacheValue;
     @Nullable
     private TetheringConfiguration mConfig;
 
-    public EntitlementManager(Context ctx, SharedLog log,
+    public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log,
             MockableSystemProperties systemProperties) {
         mContext = ctx;
-        mLog = log;
+        mLog = log.forSubComponent(TAG);
         mCurrentTethers = new ArraySet<Integer>();
         mSystemProperties = systemProperties;
+        mEntitlementCacheValue = new SparseIntArray();
+        mMasterHandler = tetherMasterSM.getHandler();
     }
 
     /**
@@ -128,6 +142,10 @@
      * Reference ConnectivityManager.TETHERING_{@code *} for each tether type.
      */
     public void reevaluateSimCardProvisioning() {
+        synchronized (mEntitlementCacheValue) {
+            mEntitlementCacheValue.clear();
+        }
+
         if (!mConfig.hasMobileHotspotProvisionApp()) return;
         if (carrierConfigAffirmsEntitlementCheckNotRequired()) return;
 
@@ -175,6 +193,11 @@
     }
 
     public void runUiTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
+        runUiTetherProvisioning(type, receiver);
+    }
+
+    @VisibleForTesting
+    protected void runUiTetherProvisioning(int type, ResultReceiver receiver) {
         Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING);
         intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
         intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
@@ -221,4 +244,70 @@
             Binder.restoreCallingIdentity(ident);
         }
     }
+
+    private ResultReceiver buildProxyReceiver(int type, final ResultReceiver receiver) {
+        ResultReceiver rr = new ResultReceiver(mMasterHandler) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                int updatedCacheValue = updateEntitlementCacheValue(type, resultCode);
+                receiver.send(updatedCacheValue, null);
+            }
+        };
+
+        return writeToParcel(rr);
+    }
+
+    private ResultReceiver writeToParcel(final ResultReceiver receiver) {
+        // This is necessary to avoid unmarshalling issues when sending the receiver
+        // across processes.
+        Parcel parcel = Parcel.obtain();
+        receiver.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel);
+        parcel.recycle();
+        return receiverForSending;
+    }
+
+    /**
+     * Update the last entitlement value to internal cache
+     *
+     * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+     * @param resultCode last entitlement value
+     * @return the last updated entitlement value
+     */
+    public int updateEntitlementCacheValue(int type, int resultCode) {
+        if (DBG) {
+            Log.d(TAG, "updateEntitlementCacheValue: " + type + ", result: " + resultCode);
+        }
+        synchronized (mEntitlementCacheValue) {
+            if (resultCode == TETHER_ERROR_NO_ERROR) {
+                mEntitlementCacheValue.put(type, resultCode);
+                return resultCode;
+            } else {
+                mEntitlementCacheValue.put(type, TETHER_ERROR_PROVISION_FAILED);
+                return TETHER_ERROR_PROVISION_FAILED;
+            }
+        }
+    }
+
+    /** Get the last value of the tethering entitlement check. */
+    public void getLatestTetheringEntitlementValue(int downstream, ResultReceiver receiver,
+            boolean showEntitlementUi) {
+        if (!isTetherProvisioningRequired()) {
+            receiver.send(TETHER_ERROR_NO_ERROR, null);
+            return;
+        }
+
+        final int cacheValue;
+        synchronized (mEntitlementCacheValue) {
+            cacheValue = mEntitlementCacheValue.get(
+                downstream, TETHER_ERROR_ENTITLEMENT_UNKONWN);
+        }
+        if (cacheValue == TETHER_ERROR_NO_ERROR || !showEntitlementUi) {
+            receiver.send(cacheValue, null);
+        } else {
+            ResultReceiver proxy = buildProxyReceiver(downstream, receiver);
+            runUiTetherProvisioning(downstream, proxy);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
index a42efe9..6d6f81e 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
@@ -81,8 +81,8 @@
     /**
      * Get a reference to the EntitlementManager to be used by tethering.
      */
-    public EntitlementManager getEntitlementManager(Context ctx, SharedLog log,
-            MockableSystemProperties systemProperties) {
-        return new EntitlementManager(ctx, log, systemProperties);
+    public EntitlementManager getEntitlementManager(Context ctx, StateMachine target,
+            SharedLog log, MockableSystemProperties systemProperties) {
+        return new EntitlementManager(ctx, target, log, systemProperties);
     }
 }
diff --git a/services/core/java/com/android/server/dreams/OWNERS b/services/core/java/com/android/server/dreams/OWNERS
index 3c9bbf8..426f002 100644
--- a/services/core/java/com/android/server/dreams/OWNERS
+++ b/services/core/java/com/android/server/dreams/OWNERS
@@ -1,3 +1,3 @@
-dsandler@google.com
+dsandler@android.com
 michaelwr@google.com
 roosa@google.com
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 60d7925..33b8641 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -51,6 +51,8 @@
 per-file UserManagerService.java = yamasani@google.com
 per-file UserRestrictionsUtils.java = omakoto@google.com
 per-file UserRestrictionsUtils.java = yamasani@google.com
+per-file UserRestrictionsUtils.java = rubinxu@google.com
+per-file UserRestrictionsUtils.java = sandness@google.com
 
 # security
 per-file KeySetHandle.java = cbrubaker@google.com
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
old mode 100644
new mode 100755
index c1607e9..f08e585
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -24,7 +24,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.PackageManager;
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiDeviceInfo;
 import android.hardware.hdmi.HdmiHotplugEvent;
@@ -46,7 +45,6 @@
 import android.media.tv.TvInputHardwareInfo;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvStreamConfig;
-import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -56,7 +54,6 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
-import android.view.KeyEvent;
 import android.view.Surface;
 
 import com.android.internal.util.DumpUtils;
@@ -943,7 +940,7 @@
                         sinkChannelMask = sinkConfig.channelMask();
                     }
                     if (sinkFormat == AudioFormat.ENCODING_DEFAULT) {
-                        sinkChannelMask = sinkConfig.format();
+                        sinkFormat = sinkConfig.format();
                     }
                 }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3ecbd47..75cd82e 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -758,6 +758,7 @@
     private void startOtherServices() {
         final Context context = mSystemContext;
         VibratorService vibrator = null;
+        DynamicAndroidService dynamicAndroid = null;
         IStorageManager storageManager = null;
         NetworkManagementService networkManagement = null;
         IpSecService ipSecService = null;
@@ -867,6 +868,11 @@
             ServiceManager.addService("vibrator", vibrator);
             traceEnd();
 
+            traceBeginAndSlog("StartDynamicAndroidService");
+            dynamicAndroid = new DynamicAndroidService(context);
+            ServiceManager.addService("dynamic_android", dynamicAndroid);
+            traceEnd();
+
             if (!isWatch) {
                 traceBeginAndSlog("StartConsumerIrService");
                 consumerIr = new ConsumerIrService(context);
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 30c7de5..638ec95 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -9,12 +9,6 @@
         "java/android/net/ip/InterfaceController.java", // TODO: move to NetworkStack with tethering
         "java/android/net/util/InterfaceParams.java", // TODO: move to NetworkStack with IpServer
         "java/android/net/shared/*.java",
-    ],
-}
-
-java_library {
-    name: "services-netlink-lib",
-    srcs: [
         "java/android/net/netlink/*.java",
-    ]
+    ],
 }
diff --git a/services/net/java/android/net/ip/InterfaceController.java b/services/net/java/android/net/ip/InterfaceController.java
index b3af67c..970bc9c 100644
--- a/services/net/java/android/net/ip/InterfaceController.java
+++ b/services/net/java/android/net/ip/InterfaceController.java
@@ -17,7 +17,6 @@
 package android.net.ip;
 
 import android.net.INetd;
-import android.net.InterfaceConfiguration;
 import android.net.InterfaceConfigurationParcel;
 import android.net.LinkAddress;
 import android.net.util.SharedLog;
@@ -49,14 +48,18 @@
         mLog = log;
     }
 
-    private boolean setInterfaceConfig(InterfaceConfiguration config) {
-        final InterfaceConfigurationParcel cfgParcel = config.toParcel(mIfName);
-
+    private boolean setInterfaceAddress(LinkAddress addr) {
+        final InterfaceConfigurationParcel ifConfig = new InterfaceConfigurationParcel();
+        ifConfig.ifName = mIfName;
+        ifConfig.ipv4Addr = addr.getAddress().getHostAddress();
+        ifConfig.prefixLength = addr.getPrefixLength();
+        ifConfig.hwAddr = "";
+        ifConfig.flags = new String[0];
         try {
-            mNetd.interfaceSetCfg(cfgParcel);
+            mNetd.interfaceSetCfg(ifConfig);
         } catch (RemoteException | ServiceSpecificException e) {
             logError("Setting IPv4 address to %s/%d failed: %s",
-                    cfgParcel.ipv4Addr, cfgParcel.prefixLength, e);
+                    ifConfig.ipv4Addr, ifConfig.prefixLength, e);
             return false;
         }
         return true;
@@ -69,18 +72,14 @@
         if (!(address.getAddress() instanceof Inet4Address)) {
             return false;
         }
-        final InterfaceConfiguration ifConfig = new InterfaceConfiguration();
-        ifConfig.setLinkAddress(address);
-        return setInterfaceConfig(ifConfig);
+        return setInterfaceAddress(address);
     }
 
     /**
      * Clear the IPv4Address of the interface.
      */
     public boolean clearIPv4Address() {
-        final InterfaceConfiguration ifConfig = new InterfaceConfiguration();
-        ifConfig.setLinkAddress(new LinkAddress("0.0.0.0/0"));
-        return setInterfaceConfig(ifConfig);
+        return setInterfaceAddress(new LinkAddress("0.0.0.0/0"));
     }
 
     private boolean setEnableIPv6(boolean enabled) {
diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java
index f7360f5..7910c9a 100644
--- a/services/net/java/android/net/ip/IpServer.java
+++ b/services/net/java/android/net/ip/IpServer.java
@@ -40,7 +40,7 @@
 import android.net.ip.RouterAdvertisementDaemon.RaParams;
 import android.net.util.InterfaceParams;
 import android.net.util.InterfaceSet;
-import android.net.shared.NetdService;
+import android.net.util.NetdService;
 import android.net.util.SharedLog;
 import android.os.INetworkManagementService;
 import android.os.Looper;
diff --git a/services/net/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java
index 2a98d90..16f72bd 100644
--- a/services/net/java/android/net/netlink/NetlinkSocket.java
+++ b/services/net/java/android/net/netlink/NetlinkSocket.java
@@ -27,14 +27,13 @@
 import static android.system.OsConstants.SO_RCVTIMEO;
 import static android.system.OsConstants.SO_SNDTIMEO;
 
+import android.net.util.SocketUtils;
 import android.system.ErrnoException;
 import android.system.Os;
-import android.system.StructTimeval;
 import android.util.Log;
 
-import libcore.io.IoUtils;
-
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.net.SocketException;
 import java.nio.ByteBuffer;
@@ -95,7 +94,11 @@
             Log.e(TAG, errPrefix, e);
             throw new ErrnoException(errPrefix, EIO, e);
         } finally {
-            IoUtils.closeQuietly(fd);
+            try {
+                SocketUtils.closeSocket(fd);
+            } catch (IOException e) {
+                // Nothing we can do here
+            }
         }
     }
 
@@ -106,7 +109,7 @@
     }
 
     public static void connectToKernel(FileDescriptor fd) throws ErrnoException, SocketException {
-        Os.connect(fd, makeNetlinkSocketAddress(0, 0));
+        SocketUtils.connectSocket(fd, makeNetlinkSocketAddress(0, 0));
     }
 
     private static void checkTimeout(long timeoutMs) {
@@ -125,7 +128,7 @@
             throws ErrnoException, IllegalArgumentException, InterruptedIOException {
         checkTimeout(timeoutMs);
 
-        Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(timeoutMs));
+        SocketUtils.setSocketTimeValueOption(fd, SOL_SOCKET, SO_RCVTIMEO, timeoutMs);
 
         ByteBuffer byteBuffer = ByteBuffer.allocate(bufsize);
         int length = Os.read(fd, byteBuffer);
@@ -148,7 +151,7 @@
             FileDescriptor fd, byte[] bytes, int offset, int count, long timeoutMs)
             throws ErrnoException, IllegalArgumentException, InterruptedIOException {
         checkTimeout(timeoutMs);
-        Os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(timeoutMs));
+        SocketUtils.setSocketTimeValueOption(fd, SOL_SOCKET, SO_SNDTIMEO, timeoutMs);
         return Os.write(fd, bytes, offset, count);
     }
 }
diff --git a/services/net/java/android/net/shared/InitialConfiguration.java b/services/net/java/android/net/shared/InitialConfiguration.java
index bc2373f..4ad7138 100644
--- a/services/net/java/android/net/shared/InitialConfiguration.java
+++ b/services/net/java/android/net/shared/InitialConfiguration.java
@@ -20,6 +20,7 @@
 import static android.net.shared.ParcelableUtil.toParcelableArray;
 import static android.text.TextUtils.join;
 
+import android.net.InetAddresses;
 import android.net.InitialConfigurationParcelable;
 import android.net.IpPrefix;
 import android.net.IpPrefixParcelable;
@@ -27,7 +28,7 @@
 import android.net.LinkAddressParcelable;
 import android.net.RouteInfo;
 
-import java.net.Inet6Address;
+import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.util.HashSet;
 import java.util.List;
@@ -43,6 +44,8 @@
     private static final int RFC6177_MIN_PREFIX_LENGTH = 48;
     private static final int RFC7421_PREFIX_LENGTH = 64;
 
+    public static final InetAddress INET6_ANY = InetAddresses.parseNumericAddress("::");
+
     /**
      * Create a InitialConfiguration that is a copy of the specified configuration.
      */
@@ -102,7 +105,7 @@
             return false;
         }
         // There no more than one IPv4 address
-        if (ipAddresses.stream().filter(LinkAddress::isIPv4).count() > 1) {
+        if (ipAddresses.stream().filter(InitialConfiguration::isIPv4).count() > 1) {
             return false;
         }
 
@@ -184,11 +187,11 @@
     }
 
     private static boolean isPrefixLengthCompliant(LinkAddress addr) {
-        return addr.isIPv4() || isCompliantIPv6PrefixLength(addr.getPrefixLength());
+        return isIPv4(addr) || isCompliantIPv6PrefixLength(addr.getPrefixLength());
     }
 
     private static boolean isPrefixLengthCompliant(IpPrefix prefix) {
-        return prefix.isIPv4() || isCompliantIPv6PrefixLength(prefix.getPrefixLength());
+        return isIPv4(prefix) || isCompliantIPv6PrefixLength(prefix.getPrefixLength());
     }
 
     private static boolean isCompliantIPv6PrefixLength(int prefixLength) {
@@ -196,8 +199,16 @@
                 && (prefixLength <= RFC7421_PREFIX_LENGTH);
     }
 
+    private static boolean isIPv4(IpPrefix prefix) {
+        return prefix.getAddress() instanceof Inet4Address;
+    }
+
+    private static boolean isIPv4(LinkAddress addr) {
+        return addr.getAddress() instanceof Inet4Address;
+    }
+
     private static boolean isIPv6DefaultRoute(IpPrefix prefix) {
-        return prefix.getAddress().equals(Inet6Address.ANY);
+        return prefix.getAddress().equals(INET6_ANY);
     }
 
     private static boolean isIPv6GUA(LinkAddress addr) {
diff --git a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
index 0007350..1f0525e 100644
--- a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
+++ b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
@@ -44,11 +44,11 @@
             @Nullable StaticIpConfiguration config) {
         if (config == null) return null;
         final StaticIpConfigurationParcelable p = new StaticIpConfigurationParcelable();
-        p.ipAddress = LinkPropertiesParcelableUtil.toStableParcelable(config.ipAddress);
-        p.gateway = parcelAddress(config.gateway);
+        p.ipAddress = LinkPropertiesParcelableUtil.toStableParcelable(config.getIpAddress());
+        p.gateway = parcelAddress(config.getGateway());
         p.dnsServers = toParcelableArray(
-                config.dnsServers, IpConfigurationParcelableUtil::parcelAddress, String.class);
-        p.domains = config.domains;
+                config.getDnsServers(), IpConfigurationParcelableUtil::parcelAddress, String.class);
+        p.domains = config.getDomains();
         return p;
     }
 
@@ -59,11 +59,13 @@
             @Nullable StaticIpConfigurationParcelable p) {
         if (p == null) return null;
         final StaticIpConfiguration config = new StaticIpConfiguration();
-        config.ipAddress = LinkPropertiesParcelableUtil.fromStableParcelable(p.ipAddress);
-        config.gateway = unparcelAddress(p.gateway);
-        config.dnsServers.addAll(fromParcelableArray(
-                p.dnsServers, IpConfigurationParcelableUtil::unparcelAddress));
-        config.domains = p.domains;
+        config.setIpAddress(LinkPropertiesParcelableUtil.fromStableParcelable(p.ipAddress));
+        config.setGateway(unparcelAddress(p.gateway));
+        for (InetAddress addr : fromParcelableArray(
+                p.dnsServers, IpConfigurationParcelableUtil::unparcelAddress)) {
+            config.addDnsServer(addr);
+        }
+        config.setDomains(p.domains);
         return config;
     }
 
diff --git a/services/net/java/android/net/shared/NetdService.java b/services/net/java/android/net/util/NetdService.java
similarity index 99%
rename from services/net/java/android/net/shared/NetdService.java
rename to services/net/java/android/net/util/NetdService.java
index f5ae725..d4cd5bd 100644
--- a/services/net/java/android/net/shared/NetdService.java
+++ b/services/net/java/android/net/util/NetdService.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.net.shared;
+package android.net.util;
 
 import android.content.Context;
 import android.net.INetd;
diff --git a/services/tests/servicestests/src/com/android/server/DynamicAndroidServiceTest.java b/services/tests/servicestests/src/com/android/server/DynamicAndroidServiceTest.java
new file mode 100644
index 0000000..1494284
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/DynamicAndroidServiceTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.os.IDynamicAndroidService;
+import android.os.ServiceManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+public class DynamicAndroidServiceTest extends AndroidTestCase {
+    private static final String TAG = "DynamicAndroidServiceTests";
+    private IDynamicAndroidService mService;
+
+    @Override
+    protected void setUp() throws Exception {
+        mService =
+                IDynamicAndroidService.Stub.asInterface(
+                        ServiceManager.getService("dynamic_android"));
+    }
+
+    @LargeTest
+    public void test1() {
+        assertTrue("dynamic_android service available", mService != null);
+        try {
+            mService.startInstallation(1 << 20, 8 << 30);
+            fail("DynamicAndroidService did not throw SecurityException as expected");
+        } catch (SecurityException e) {
+            // expected
+        } catch (Exception e) {
+            fail(e.toString());
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 8461166..39fc715 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -124,6 +124,7 @@
 
     static class MyInjector extends AppStandbyController.Injector {
         long mElapsedRealtime;
+        boolean mIsAppIdleEnabled = true;
         boolean mIsCharging;
         List<String> mPowerSaveWhitelistExceptIdle = new ArrayList<>();
         boolean mDisplayOn;
@@ -155,7 +156,7 @@
 
         @Override
         boolean isAppIdleEnabled() {
-            return true;
+            return mIsAppIdleEnabled;
         }
 
         @Override
@@ -266,6 +267,13 @@
         }
     }
 
+    private void setAppIdleEnabled(AppStandbyController controller, boolean enabled) {
+        mInjector.mIsAppIdleEnabled = enabled;
+        if (controller != null) {
+            controller.setAppIdleEnabled(enabled);
+        }
+    }
+
     private AppStandbyController setupController() throws Exception {
         mInjector.mElapsedRealtime = 0;
         setupPm(mInjector.getContext().getPackageManager());
@@ -335,7 +343,7 @@
         public void onParoleStateChanged(boolean isParoleOn) {
             synchronized (this) {
                 // Only record information if it is being looked for
-                if (mLatch.getCount() > 0) {
+                if (mLatch != null && mLatch.getCount() > 0) {
                     mOnParole = isParoleOn;
                     mLastParoleChangeTime = getCurrentTime();
                     mLatch.countDown();
@@ -396,6 +404,74 @@
                 marginOfError);
     }
 
+    @Test
+    public void testEnabledState() throws Exception {
+        TestParoleListener paroleListener = new TestParoleListener();
+        mController.addListener(paroleListener);
+        long lastUpdateTime;
+
+        // Test that listeners are notified if enabled changes when the device is not in parole.
+        setChargingState(mController, false);
+
+        // Start off not enabled. Device is effectively on permanent parole.
+        setAppIdleEnabled(mController, false);
+
+        // Enable controller
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, true);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertFalse(paroleListener.mOnParole);
+        lastUpdateTime = paroleListener.getLastParoleChangeTime();
+
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, true);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertFalse(paroleListener.mOnParole);
+        // Make sure AppStandbyController doesn't notify listeners when there's no change.
+        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
+
+        // Disable controller
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, false);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertTrue(paroleListener.mOnParole);
+        lastUpdateTime = paroleListener.getLastParoleChangeTime();
+
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, false);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertTrue(paroleListener.mOnParole);
+        // Make sure AppStandbyController doesn't notify listeners when there's no change.
+        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
+
+
+        // Test that listeners aren't notified if enabled status changes when the device is already
+        // in parole.
+
+        // A device is in parole whenever it's charging.
+        setChargingState(mController, true);
+
+        // Start off not enabled.
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, false);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertTrue(paroleListener.mOnParole);
+        lastUpdateTime = paroleListener.getLastParoleChangeTime();
+
+        // Test that toggling doesn't notify the listener.
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, true);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertTrue(paroleListener.mOnParole);
+        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
+
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, false);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertTrue(paroleListener.mOnParole);
+        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
+    }
+
     private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket) {
         mInjector.mElapsedRealtime = elapsedTime;
         controller.checkIdleStates(USER_ID);
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 9c62700..e380d7a 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -30,18 +30,19 @@
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_BACKGROUND;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_NOTIFICATION_SEEN;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SLICE_PINNED;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SLICE_PINNED_PRIV;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYNC_ADAPTER;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYSTEM_INTERACTION;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYSTEM_UPDATE;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACTION;
-import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SLICE_PINNED;
-import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SLICE_PINNED_PRIV;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+
 import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
 import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 
@@ -340,14 +341,21 @@
     }
 
     void setAppIdleEnabled(boolean enabled) {
-        mAppIdleEnabled = enabled;
+        synchronized (mAppIdleLock) {
+            if (mAppIdleEnabled != enabled) {
+                final boolean oldParoleState = isParoledOrCharging();
+                mAppIdleEnabled = enabled;
+                if (isParoledOrCharging() != oldParoleState) {
+                    postParoleStateChanged();
+                }
+            }
+        }
     }
 
     public void onBootPhase(int phase) {
         mInjector.onBootPhase(phase);
         if (phase == PHASE_SYSTEM_SERVICES_READY) {
             Slog.d(TAG, "Setting app idle enabled state");
-            setAppIdleEnabled(mInjector.isAppIdleEnabled());
             // Observe changes to the threshold
             SettingsObserver settingsObserver = new SettingsObserver(mHandler);
             settingsObserver.registerObserver();
@@ -1807,8 +1815,6 @@
                         mContext.getContentResolver(),
                         Global.APP_IDLE_CONSTANTS));
             }
-            // Check if app_idle_enabled has changed
-            setAppIdleEnabled(mInjector.isAppIdleEnabled());
 
             // Look at global settings for this.
             // TODO: Maybe apply different thresholds for different users.
@@ -1880,6 +1886,10 @@
                         (KEY_STABLE_CHARGING_THRESHOLD,
                                 COMPRESS_TIME ? ONE_MINUTE : DEFAULT_STABLE_CHARGING_THRESHOLD);
             }
+
+            // Check if app_idle_enabled has changed. Do this after getting the rest of the settings
+            // in case we need to change something based on the new values.
+            setAppIdleEnabled(mInjector.isAppIdleEnabled());
         }
 
         long[] parseLongArray(String values, long[] defaults) {
diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp
index f5b4308..37caeb2 100644
--- a/startop/view_compiler/Android.bp
+++ b/startop/view_compiler/Android.bp
@@ -58,6 +58,8 @@
         "util.cc",
         "layout_validation.cc",
     ],
+    // b/123880763, clang-tidy analyzer has segmentation fault with dex_builder.cc
+    tidy_checks: ["-clang-analyzer-*"],
     host_supported: true,
 }
 
diff --git a/startop/view_compiler/TEST_MAPPING b/startop/view_compiler/TEST_MAPPING
index 7006075..5f7d3f9 100644
--- a/startop/view_compiler/TEST_MAPPING
+++ b/startop/view_compiler/TEST_MAPPING
@@ -4,6 +4,14 @@
       "name": "dex-builder-test"
     },
     {
+      "name": "CtsViewTestCases",
+      "options": [
+        {
+          "include-filter": "android.view.cts.PrecompiledLayoutTest"
+        }
+      ]
+    },
+    {
       "name": "view-compiler-tests",
       "host": true
     }
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
index a78f7d5..4c1a0dc7 100644
--- a/startop/view_compiler/dex_builder.cc
+++ b/startop/view_compiler/dex_builder.cc
@@ -21,8 +21,6 @@
 #include <fstream>
 #include <memory>
 
-#define DCHECK_NOT_NULL(p) DCHECK((p) != nullptr)
-
 namespace startop {
 namespace dex {
 
@@ -32,6 +30,8 @@
 using ::dex::kAccPublic;
 using Op = Instruction::Op;
 
+using Opcode = ::art::Instruction::Code;
+
 const TypeDescriptor TypeDescriptor::Int() { return TypeDescriptor{"I"}; };
 const TypeDescriptor TypeDescriptor::Void() { return TypeDescriptor{"V"}; };
 
@@ -42,6 +42,23 @@
 // Strings lengths can be 32 bits long, but encoded as LEB128 this can take up to five bytes.
 constexpr size_t kMaxEncodedStringLength{5};
 
+// Converts invoke-* to invoke-*/range
+constexpr Opcode InvokeToInvokeRange(Opcode opcode) {
+  switch (opcode) {
+    case ::art::Instruction::INVOKE_VIRTUAL:
+      return ::art::Instruction::INVOKE_VIRTUAL_RANGE;
+    case ::art::Instruction::INVOKE_DIRECT:
+      return ::art::Instruction::INVOKE_DIRECT_RANGE;
+    case ::art::Instruction::INVOKE_STATIC:
+      return ::art::Instruction::INVOKE_STATIC_RANGE;
+    case ::art::Instruction::INVOKE_INTERFACE:
+      return ::art::Instruction::INVOKE_INTERFACE_RANGE;
+    default:
+      LOG(FATAL) << opcode << " is not a recognized invoke opcode.";
+      UNREACHABLE();
+  }
+}
+
 }  // namespace
 
 std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode) {
@@ -55,6 +72,9 @@
     case Instruction::Op::kMove:
       out << "kMove";
       return out;
+    case Instruction::Op::kMoveObject:
+      out << "kMoveObject";
+      return out;
     case Instruction::Op::kInvokeVirtual:
       out << "kInvokeVirtual";
       return out;
@@ -233,6 +253,11 @@
   return shorty;
 }
 
+const TypeDescriptor& Prototype::ArgType(size_t index) const {
+  CHECK_LT(index, param_types_.size());
+  return param_types_[index];
+}
+
 ClassBuilder::ClassBuilder(DexBuilder* parent, const std::string& name, ir::Class* class_def)
     : parent_(parent), type_descriptor_{TypeDescriptor::FromClassname(name)}, class_(class_def) {}
 
@@ -257,10 +282,10 @@
   method->access_flags = kAccPublic | ::dex::kAccStatic;
 
   auto* code = dex_->Alloc<ir::Code>();
-  DCHECK_NOT_NULL(decl_->prototype);
+  CHECK(decl_->prototype != nullptr);
   size_t const num_args =
       decl_->prototype->param_types != nullptr ? decl_->prototype->param_types->types.size() : 0;
-  code->registers = num_registers_ + num_args;
+  code->registers = num_registers_ + num_args + kMaxScratchRegisters;
   code->ins_count = num_args;
   EncodeInstructions();
   code->instructions = slicer::ArrayView<const ::dex::u2>(buffer_.data(), buffer_.size());
@@ -292,7 +317,7 @@
 }
 
 void MethodBuilder::BuildConst4(Value target, int value) {
-  DCHECK_LT(value, 16);
+  CHECK_LT(value, 16);
   AddInstruction(Instruction::OpWithArgs(Op::kMove, target, Value::Immediate(value)));
 }
 
@@ -315,6 +340,7 @@
     case Instruction::Op::kReturnObject:
       return EncodeReturn(instruction, ::art::Instruction::RETURN_OBJECT);
     case Instruction::Op::kMove:
+    case Instruction::Op::kMoveObject:
       return EncodeMove(instruction);
     case Instruction::Op::kInvokeVirtual:
       return EncodeInvoke(instruction, art::Instruction::INVOKE_VIRTUAL);
@@ -338,33 +364,43 @@
 }
 
 void MethodBuilder::EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode) {
-  DCHECK(!instruction.dest().has_value());
+  CHECK(!instruction.dest().has_value());
   if (instruction.args().size() == 0) {
     Encode10x(art::Instruction::RETURN_VOID);
   } else {
-    DCHECK_EQ(1, instruction.args().size());
+    CHECK_EQ(1, instruction.args().size());
     size_t source = RegisterValue(instruction.args()[0]);
     Encode11x(opcode, source);
   }
 }
 
 void MethodBuilder::EncodeMove(const Instruction& instruction) {
-  DCHECK_EQ(Instruction::Op::kMove, instruction.opcode());
-  DCHECK(instruction.dest().has_value());
-  DCHECK(instruction.dest()->is_register() || instruction.dest()->is_parameter());
-  DCHECK_EQ(1, instruction.args().size());
+  CHECK(Instruction::Op::kMove == instruction.opcode() ||
+        Instruction::Op::kMoveObject == instruction.opcode());
+  CHECK(instruction.dest().has_value());
+  CHECK(instruction.dest()->is_variable());
+  CHECK_EQ(1, instruction.args().size());
 
   const Value& source = instruction.args()[0];
 
   if (source.is_immediate()) {
     // TODO: support more registers
-    DCHECK_LT(RegisterValue(*instruction.dest()), 16);
+    CHECK_LT(RegisterValue(*instruction.dest()), 16);
     Encode11n(art::Instruction::CONST_4, RegisterValue(*instruction.dest()), source.value());
   } else if (source.is_string()) {
     constexpr size_t kMaxRegisters = 256;
-    DCHECK_LT(RegisterValue(*instruction.dest()), kMaxRegisters);
-    DCHECK_LT(source.value(), 65536);  // make sure we don't need a jumbo string
+    CHECK_LT(RegisterValue(*instruction.dest()), kMaxRegisters);
+    CHECK_LT(source.value(), 65536);  // make sure we don't need a jumbo string
     Encode21c(::art::Instruction::CONST_STRING, RegisterValue(*instruction.dest()), source.value());
+  } else if (source.is_variable()) {
+    // For the moment, we only use this when we need to reshuffle registers for
+    // an invoke instruction, meaning we are too big for the 4-bit version.
+    // We'll err on the side of caution and always generate the 16-bit form of
+    // the instruction.
+    Opcode opcode = instruction.opcode() == Instruction::Op::kMove
+                        ? ::art::Instruction::MOVE_16
+                        : ::art::Instruction::MOVE_OBJECT_16;
+    Encode32x(opcode, RegisterValue(*instruction.dest()), RegisterValue(source));
   } else {
     UNIMPLEMENTED(FATAL);
   }
@@ -373,22 +409,61 @@
 void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode) {
   constexpr size_t kMaxArgs = 5;
 
+  // Currently, we only support up to 5 arguments.
   CHECK_LE(instruction.args().size(), kMaxArgs);
 
   uint8_t arguments[kMaxArgs]{};
+  bool has_long_args = false;
   for (size_t i = 0; i < instruction.args().size(); ++i) {
     CHECK(instruction.args()[i].is_variable());
     arguments[i] = RegisterValue(instruction.args()[i]);
+    if (!IsShortRegister(arguments[i])) {
+      has_long_args = true;
+    }
   }
 
-  Encode35c(opcode,
-            instruction.args().size(),
-            instruction.method_id(),
-            arguments[0],
-            arguments[1],
-            arguments[2],
-            arguments[3],
-            arguments[4]);
+  if (has_long_args) {
+    // Some of the registers don't fit in the four bit short form of the invoke
+    // instruction, so we need to do an invoke/range. To do this, we need to
+    // first move all the arguments into contiguous temporary registers.
+    std::array<Value, kMaxArgs> scratch{GetScratchRegisters<kMaxArgs>()};
+
+    const auto& prototype = dex_->GetPrototypeByMethodId(instruction.method_id());
+    CHECK(prototype.has_value());
+
+    for (size_t i = 0; i < instruction.args().size(); ++i) {
+      Instruction::Op move_op;
+      if (opcode == ::art::Instruction::INVOKE_VIRTUAL ||
+          opcode == ::art::Instruction::INVOKE_DIRECT) {
+        // In this case, there is an implicit `this` argument, which is always an object.
+        if (i == 0) {
+          move_op = Instruction::Op::kMoveObject;
+        } else {
+          move_op = prototype->ArgType(i - 1).is_object() ? Instruction::Op::kMoveObject
+                                                          : Instruction::Op::kMove;
+        }
+      } else {
+        move_op = prototype->ArgType(i).is_object() ? Instruction::Op::kMoveObject
+                                                    : Instruction::Op::kMove;
+      }
+
+      EncodeMove(Instruction::OpWithArgs(move_op, scratch[i], instruction.args()[i]));
+    }
+
+    Encode3rc(InvokeToInvokeRange(opcode),
+              instruction.args().size(),
+              instruction.method_id(),
+              RegisterValue(scratch[0]));
+  } else {
+    Encode35c(opcode,
+              instruction.args().size(),
+              instruction.method_id(),
+              arguments[0],
+              arguments[1],
+              arguments[2],
+              arguments[3],
+              arguments[4]);
+  }
 
   // If there is a return value, add a move-result instruction
   if (instruction.dest().has_value()) {
@@ -416,26 +491,26 @@
 }
 
 void MethodBuilder::EncodeNew(const Instruction& instruction) {
-  DCHECK_EQ(Instruction::Op::kNew, instruction.opcode());
-  DCHECK(instruction.dest().has_value());
-  DCHECK(instruction.dest()->is_variable());
-  DCHECK_EQ(1, instruction.args().size());
+  CHECK_EQ(Instruction::Op::kNew, instruction.opcode());
+  CHECK(instruction.dest().has_value());
+  CHECK(instruction.dest()->is_variable());
+  CHECK_EQ(1, instruction.args().size());
 
   const Value& type = instruction.args()[0];
-  DCHECK_LT(RegisterValue(*instruction.dest()), 256);
-  DCHECK(type.is_type());
+  CHECK_LT(RegisterValue(*instruction.dest()), 256);
+  CHECK(type.is_type());
   Encode21c(::art::Instruction::NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value());
 }
 
 void MethodBuilder::EncodeCast(const Instruction& instruction) {
-  DCHECK_EQ(Instruction::Op::kCheckCast, instruction.opcode());
-  DCHECK(instruction.dest().has_value());
-  DCHECK(instruction.dest()->is_variable());
-  DCHECK_EQ(1, instruction.args().size());
+  CHECK_EQ(Instruction::Op::kCheckCast, instruction.opcode());
+  CHECK(instruction.dest().has_value());
+  CHECK(instruction.dest()->is_variable());
+  CHECK_EQ(1, instruction.args().size());
 
   const Value& type = instruction.args()[0];
-  DCHECK_LT(RegisterValue(*instruction.dest()), 256);
-  DCHECK(type.is_type());
+  CHECK_LT(RegisterValue(*instruction.dest()), 256);
+  CHECK(type.is_type());
   Encode21c(::art::Instruction::CHECK_CAST, RegisterValue(*instruction.dest()), type.value());
 }
 
@@ -443,9 +518,9 @@
   if (value.is_register()) {
     return value.value();
   } else if (value.is_parameter()) {
-    return value.value() + num_registers_;
+    return value.value() + num_registers_ + kMaxScratchRegisters;
   }
-  DCHECK(false && "Must be either a parameter or a register");
+  CHECK(false && "Must be either a parameter or a register");
   return 0;
 }
 
@@ -498,7 +573,7 @@
     // update the index -> ir node map (see tools/dexter/slicer/dex_ir_builder.cc)
     auto new_index = dex_file_->methods_indexes.AllocateIndex();
     auto& ir_node = dex_file_->methods_map[new_index];
-    SLICER_CHECK(ir_node == nullptr);
+    CHECK(ir_node == nullptr);
     ir_node = decl;
     decl->orig_index = decl->index = new_index;
 
@@ -508,6 +583,15 @@
   return entry;
 }
 
+std::optional<const Prototype> DexBuilder::GetPrototypeByMethodId(size_t method_id) const {
+  for (const auto& entry : method_id_map_) {
+    if (entry.second.id == method_id) {
+      return entry.first.prototype;
+    }
+  }
+  return {};
+}
+
 ir::Proto* DexBuilder::GetOrEncodeProto(Prototype prototype) {
   ir::Proto*& ir_proto = proto_map_[prototype];
   if (ir_proto == nullptr) {
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index 757d863..541d800 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -16,6 +16,7 @@
 #ifndef DEX_BUILDER_H_
 #define DEX_BUILDER_H_
 
+#include <array>
 #include <forward_list>
 #include <map>
 #include <optional>
@@ -70,6 +71,8 @@
   // Return the shorty descriptor, such as I or L
   std::string short_descriptor() const { return descriptor().substr(0, 1); }
 
+  bool is_object() const { return short_descriptor() == "L"; }
+
   bool operator<(const TypeDescriptor& rhs) const { return descriptor_ < rhs.descriptor_; }
 
  private:
@@ -92,6 +95,8 @@
   // Get the shorty descriptor, such as VII for (Int, Int) -> Void
   std::string Shorty() const;
 
+  const TypeDescriptor& ArgType(size_t index) const;
+
   bool operator<(const Prototype& rhs) const {
     return std::make_tuple(return_type_, param_types_) <
            std::make_tuple(rhs.return_type_, rhs.param_types_);
@@ -124,11 +129,13 @@
 
   size_t value() const { return value_; }
 
- private:
-  enum class Kind { kLocalRegister, kParameter, kImmediate, kString, kLabel, kType };
+  constexpr Value() : value_{0}, kind_{Kind::kInvalid} {}
 
-  const size_t value_;
-  const Kind kind_;
+ private:
+  enum class Kind { kInvalid, kLocalRegister, kParameter, kImmediate, kString, kLabel, kType };
+
+  size_t value_;
+  Kind kind_;
 
   constexpr Value(size_t value, Kind kind) : value_{value}, kind_{kind} {}
 };
@@ -151,6 +158,7 @@
     kInvokeStatic,
     kInvokeVirtual,
     kMove,
+    kMoveObject,
     kNew,
     kReturn,
     kReturnObject,
@@ -172,7 +180,7 @@
 
   // A cast instruction. Basically, `(type)val`
   static inline Instruction Cast(Value val, Value type) {
-    DCHECK(type.is_type());
+    CHECK(type.is_type());
     return OpWithArgs(Op::kCheckCast, val, type);
   }
 
@@ -343,21 +351,48 @@
     buffer_.push_back(b);
   }
 
+  inline void Encode32x(art::Instruction::Code opcode, uint16_t a, uint16_t b) {
+    buffer_.push_back(opcode);
+    buffer_.push_back(a);
+    buffer_.push_back(b);
+  }
+
   inline void Encode35c(art::Instruction::Code opcode, size_t a, uint16_t b, uint8_t c, uint8_t d,
                         uint8_t e, uint8_t f, uint8_t g) {
     // a|g|op|bbbb|f|e|d|c
 
     CHECK_LE(a, 5);
-    CHECK_LT(c, 16);
-    CHECK_LT(d, 16);
-    CHECK_LT(e, 16);
-    CHECK_LT(f, 16);
-    CHECK_LT(g, 16);
+    CHECK(IsShortRegister(c));
+    CHECK(IsShortRegister(d));
+    CHECK(IsShortRegister(e));
+    CHECK(IsShortRegister(f));
+    CHECK(IsShortRegister(g));
     buffer_.push_back((a << 12) | (g << 8) | opcode);
     buffer_.push_back(b);
     buffer_.push_back((f << 12) | (e << 8) | (d << 4) | c);
   }
 
+  inline void Encode3rc(art::Instruction::Code opcode, size_t a, uint16_t b, uint16_t c) {
+    CHECK_LE(a, 255);
+    buffer_.push_back((a << 8) | opcode);
+    buffer_.push_back(b);
+    buffer_.push_back(c);
+  }
+
+  static constexpr bool IsShortRegister(size_t register_value) { return register_value < 16; }
+
+  // Returns an array of num_regs scratch registers. These are guaranteed to be
+  // contiguous, so they are suitable for the invoke-*/range instructions.
+  template <int num_regs>
+  std::array<Value, num_regs> GetScratchRegisters() const {
+    static_assert(num_regs <= kMaxScratchRegisters);
+    std::array<Value, num_regs> regs;
+    for (size_t i = 0; i < num_regs; ++i) {
+      regs[i] = std::move(Value::Local(num_registers_ + i));
+    }
+    return regs;
+  }
+
   // Converts a register or parameter to its DEX register number.
   size_t RegisterValue(const Value& value) const;
 
@@ -379,6 +414,10 @@
   // A buffer to hold instructions that have been encoded.
   std::vector<::dex::u2> buffer_;
 
+  // We create some scratch registers for when we have to shuffle registers
+  // around to make legal DEX code.
+  static constexpr size_t kMaxScratchRegisters = 5;
+
   // How many registers we've allocated
   size_t num_registers_{0};
 
@@ -447,6 +486,8 @@
   const MethodDeclData& GetOrDeclareMethod(TypeDescriptor type, const std::string& name,
                                            Prototype prototype);
 
+  std::optional<const Prototype> GetPrototypeByMethodId(size_t method_id) const;
+
  private:
   // Looks up the ir::Proto* corresponding to this given prototype, or creates one if it does not
   // exist.
diff --git a/startop/view_compiler/dex_builder_test.cc b/startop/view_compiler/dex_builder_test.cc
index 61c86b4..90c256f 100644
--- a/startop/view_compiler/dex_builder_test.cc
+++ b/startop/view_compiler/dex_builder_test.cc
@@ -140,3 +140,41 @@
 
   EXPECT_TRUE(EncodeAndVerify(&dex_file));
 }
+
+// Write out and verify a DEX file that corresponds to:
+//
+// package dextest;
+// public class DexTest {
+//     public static int foo(String s) { return s.length(); }
+// }
+TEST(DexBuilderTest, VerifyDexCallManyRegisters) {
+  DexBuilder dex_file;
+
+  auto cbuilder{dex_file.MakeClass("dextest.DexTest")};
+
+  MethodBuilder method{cbuilder.CreateMethod(
+      "foo", Prototype{TypeDescriptor::Int()})};
+
+  Value result = method.MakeRegister();
+
+  // Make a bunch of registers
+  for (size_t i = 0; i < 25; ++i) {
+    method.MakeRegister();
+  }
+
+  // Now load a string literal into a register
+  Value string_val = method.MakeRegister();
+  method.BuildConstString(string_val, "foo");
+
+  MethodDeclData string_length =
+      dex_file.GetOrDeclareMethod(TypeDescriptor::FromClassname("java.lang.String"),
+                                  "length",
+                                  Prototype{TypeDescriptor::Int()});
+
+  method.AddInstruction(Instruction::InvokeVirtual(string_length.id, result, string_val));
+  method.BuildReturn(result);
+
+  method.Encode();
+
+  EXPECT_TRUE(EncodeAndVerify(&dex_file));
+}
diff --git a/startop/view_compiler/dex_builder_test/Android.bp b/startop/view_compiler/dex_builder_test/Android.bp
index d4f38ed..ac60e96 100644
--- a/startop/view_compiler/dex_builder_test/Android.bp
+++ b/startop/view_compiler/dex_builder_test/Android.bp
@@ -15,7 +15,7 @@
 //
 
 genrule {
-    name: "generate_compiled_layout",
+    name: "generate_compiled_layout1",
     tools: [":viewcompiler"],
     cmd: "$(location :viewcompiler) $(in) --dex --out $(out) --package android.startop.test",
     srcs: ["res/layout/layout1.xml"],
@@ -24,6 +24,16 @@
     ],
 }
 
+genrule {
+    name: "generate_compiled_layout2",
+    tools: [":viewcompiler"],
+    cmd: "$(location :viewcompiler) $(in) --dex --out $(out) --package android.startop.test",
+    srcs: ["res/layout/layout2.xml"],
+    out: [
+        "layout2.dex",
+    ],
+}
+
 android_test {
     name: "dex-builder-test",
     srcs: [
@@ -31,7 +41,7 @@
         "src/android/startop/test/LayoutCompilerTest.java",
     ],
     sdk_version: "current",
-    data: [":generate_dex_testcases", ":generate_compiled_layout"],
+    data: [":generate_dex_testcases", ":generate_compiled_layout1", ":generate_compiled_layout2"],
     static_libs: [
         "android-support-test",
         "guava",
diff --git a/startop/view_compiler/dex_builder_test/AndroidTest.xml b/startop/view_compiler/dex_builder_test/AndroidTest.xml
index 68d8fdc..92e2a71 100644
--- a/startop/view_compiler/dex_builder_test/AndroidTest.xml
+++ b/startop/view_compiler/dex_builder_test/AndroidTest.xml
@@ -26,6 +26,7 @@
         <option name="push" value="trivial.dex->/data/local/tmp/dex-builder-test/trivial.dex" />
         <option name="push" value="simple.dex->/data/local/tmp/dex-builder-test/simple.dex" />
         <option name="push" value="layout1.dex->/data/local/tmp/dex-builder-test/layout1.dex" />
+        <option name="push" value="layout2.dex->/data/local/tmp/dex-builder-test/layout2.dex" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/startop/view_compiler/dex_builder_test/res/layout/layout2.xml b/startop/view_compiler/dex_builder_test/res/layout/layout2.xml
new file mode 100644
index 0000000..b092e1c
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/res/layout/layout2.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TableRow
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" >
+
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Button" />
+
+        <TableRow
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" >
+
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Button" />
+            <TableRow
+                android:layout_width="match_parent"
+                android:layout_height="match_parent" >
+
+                <Button
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="Button" />
+
+                <TableRow
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent" >
+
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="Button" />
+                </TableRow>
+
+            </TableRow>
+        </TableRow>
+    </TableRow>
+</LinearLayout>
diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java
index ce3ce83..a3b1b6c 100644
--- a/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java
+++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java
@@ -36,11 +36,20 @@
     }
 
     @Test
-    public void loadAndInflaterLayout1() throws Exception {
+    public void loadAndInflateLayout1() throws Exception {
         ClassLoader dex_file = loadDexFile("layout1.dex");
         Class compiled_view = dex_file.loadClass("android.startop.test.CompiledView");
         Method layout1 = compiled_view.getMethod("layout1", Context.class, int.class);
         Context context = InstrumentationRegistry.getTargetContext();
         layout1.invoke(null, context, R.layout.layout1);
     }
+
+    @Test
+    public void loadAndInflateLayout2() throws Exception {
+        ClassLoader dex_file = loadDexFile("layout2.dex");
+        Class compiled_view = dex_file.loadClass("android.startop.test.CompiledView");
+        Method layout1 = compiled_view.getMethod("layout2", Context.class, int.class);
+        Context context = InstrumentationRegistry.getTargetContext();
+        layout1.invoke(null, context, R.layout.layout1);
+    }
 }
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 2820836..dcaa499 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -239,6 +239,30 @@
             "android.telecom.event.HANDOVER_FAILED";
 
     public static class Details {
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(
+                prefix = { "DIRECTION_" },
+                value = {DIRECTION_UNKNOWN, DIRECTION_INCOMING, DIRECTION_OUTGOING})
+        public @interface CallDirection {}
+
+        /**
+         * Indicates that the call is neither and incoming nor an outgoing call.  This can be the
+         * case for calls reported directly by a {@link ConnectionService} in special cases such as
+         * call handovers.
+         */
+        public static final int DIRECTION_UNKNOWN = -1;
+
+        /**
+         * Indicates that the call is an incoming call.
+         */
+        public static final int DIRECTION_INCOMING = 0;
+
+        /**
+         * Indicates that the call is an outgoing call.
+         */
+        public static final int DIRECTION_OUTGOING = 1;
+
 
         /** Call can currently be put on hold or unheld. */
         public static final int CAPABILITY_HOLD = 0x00000001;
@@ -519,6 +543,7 @@
         private final Bundle mIntentExtras;
         private final long mCreationTimeMillis;
         private final CallIdentification mCallIdentification;
+        private final @CallDirection int mCallDirection;
 
         /**
          * Whether the supplied capabilities  supports the specified capability.
@@ -838,6 +863,14 @@
             return mCallIdentification;
         }
 
+        /**
+         * Indicates whether the call is an incoming or outgoing call.
+         * @return The call's direction.
+         */
+        public @CallDirection int getCallDirection() {
+            return mCallDirection;
+        }
+
         @Override
         public boolean equals(Object o) {
             if (o instanceof Details) {
@@ -859,7 +892,8 @@
                         areBundlesEqual(mExtras, d.mExtras) &&
                         areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
                         Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis) &&
-                        Objects.equals(mCallIdentification, d.mCallIdentification);
+                        Objects.equals(mCallIdentification, d.mCallIdentification) &&
+                        Objects.equals(mCallDirection, d.mCallDirection);
             }
             return false;
         }
@@ -881,7 +915,8 @@
                             mExtras,
                             mIntentExtras,
                             mCreationTimeMillis,
-                            mCallIdentification);
+                            mCallIdentification,
+                            mCallDirection);
         }
 
         /** {@hide} */
@@ -902,7 +937,8 @@
                 Bundle extras,
                 Bundle intentExtras,
                 long creationTimeMillis,
-                CallIdentification callIdentification) {
+                CallIdentification callIdentification,
+                int callDirection) {
             mTelecomCallId = telecomCallId;
             mHandle = handle;
             mHandlePresentation = handlePresentation;
@@ -920,6 +956,7 @@
             mIntentExtras = intentExtras;
             mCreationTimeMillis = creationTimeMillis;
             mCallIdentification = callIdentification;
+            mCallDirection = callDirection;
         }
 
         /** {@hide} */
@@ -941,7 +978,8 @@
                     parcelableCall.getExtras(),
                     parcelableCall.getIntentExtras(),
                     parcelableCall.getCreationTimeMillis(),
-                    parcelableCall.getCallIdentification());
+                    parcelableCall.getCallIdentification(),
+                    parcelableCall.getCallDirection());
         }
 
         @Override
diff --git a/telecomm/java/android/telecom/CallIdentification.java b/telecomm/java/android/telecom/CallIdentification.java
index 97af06c..87834fd 100644
--- a/telecomm/java/android/telecom/CallIdentification.java
+++ b/telecomm/java/android/telecom/CallIdentification.java
@@ -250,8 +250,8 @@
         mDetails = details;
         mPhoto = photo;
         mNuisanceConfidence = nuisanceConfidence;
-        mCallScreeningAppName = callScreeningPackageName;
-        mCallScreeningPackageName = callScreeningAppName;
+        mCallScreeningAppName = callScreeningAppName;
+        mCallScreeningPackageName = callScreeningPackageName;
     }
 
     private String mName;
@@ -430,4 +430,22 @@
         return Objects.hash(mName, mDescription, mDetails, mPhoto, mNuisanceConfidence,
                 mCallScreeningAppName, mCallScreeningPackageName);
     }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("[CallId mName=");
+        sb.append(Log.pii(mName));
+        sb.append(", mDesc=");
+        sb.append(mDescription);
+        sb.append(", mDet=");
+        sb.append(mDetails);
+        sb.append(", conf=");
+        sb.append(mNuisanceConfidence);
+        sb.append(", appName=");
+        sb.append(mCallScreeningAppName);
+        sb.append(", pkgName=");
+        sb.append(mCallScreeningPackageName);
+        return sb.toString();
+    }
 }
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index be96b3c..826ad82 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -21,6 +21,7 @@
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -33,8 +34,9 @@
 
 /**
  * This service can be implemented by the default dialer (see
- * {@link TelecomManager#getDefaultDialerPackage()}) to allow or disallow incoming calls before
- * they are shown to a user.
+ * {@link TelecomManager#getDefaultDialerPackage()}) or a third party app to allow or disallow
+ * incoming calls before they are shown to a user.  This service can also provide
+ * {@link CallIdentification} information for calls.
  * <p>
  * Below is an example manifest registration for a {@code CallScreeningService}.
  * <pre>
@@ -56,6 +58,34 @@
  *     information about a {@link Call.Details call} which will be shown to the user in the
  *     Dialer app.</li>
  * </ol>
+ * <p>
+ * <h2>Becoming the {@link CallScreeningService}</h2>
+ * Telecom will bind to a single app chosen by the user which implements the
+ * {@link CallScreeningService} API when there are new incoming and outgoing calls.
+ * <p>
+ * The code snippet below illustrates how your app can request that it fills the call screening
+ * role.
+ * <pre>
+ * {@code
+ * private static final int REQUEST_ID = 1;
+ *
+ * public void requestRole() {
+ *     RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
+ *     Intent intent = roleManager.createRequestRoleIntent("android.app.role.CALL_SCREENING_APP");
+ *     startActivityForResult(intent, REQUEST_ID);
+ * }
+ *
+ * &#64;Override
+ * public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ *     if (requestCode == REQUEST_ID) {
+ *         if (resultCode == android.app.Activity.RESULT_OK) {
+ *             // Your app is now the call screening app
+ *         } else {
+ *             // Your app is not the call screening app
+ *         }
+ *     }
+ * }
+ * </pre>
  */
 public abstract class CallScreeningService extends Service {
     /**
@@ -222,30 +252,46 @@
     }
 
     /**
-     * Called when a new incoming call is added.
-     * {@link CallScreeningService#respondToCall(Call.Details, CallScreeningService.CallResponse)}
-     * should be called to allow or disallow the call.
+     * Called when a new incoming or outgoing call is added which is not in the user's contact list.
+     * <p>
+     * A {@link CallScreeningService} must indicate whether an incoming call is allowed or not by
+     * calling
+     * {@link CallScreeningService#respondToCall(Call.Details, CallScreeningService.CallResponse)}.
+     * Your app can tell if a call is an incoming call by checking to see if
+     * {@link Call.Details#getCallDirection()} is {@link Call.Details#DIRECTION_INCOMING}.
+     * <p>
+     * For incoming or outgoing calls, the {@link CallScreeningService} can call
+     * {@link #provideCallIdentification(Call.Details, CallIdentification)} in order to provide
+     * {@link CallIdentification} for the call.
      * <p>
      * Note: The {@link Call.Details} instance provided to a call screening service will only have
      * the following properties set.  The rest of the {@link Call.Details} properties will be set to
      * their default value or {@code null}.
      * <ul>
-     *     <li>{@link Call.Details#getState()}</li>
+     *     <li>{@link Call.Details#getCallDirection()}</li>
      *     <li>{@link Call.Details#getConnectTimeMillis()}</li>
      *     <li>{@link Call.Details#getCreationTimeMillis()}</li>
      *     <li>{@link Call.Details#getHandle()}</li>
      *     <li>{@link Call.Details#getHandlePresentation()}</li>
      * </ul>
+     * <p>
+     * Only calls where the {@link Call.Details#getHandle() handle} {@link Uri#getScheme() scheme}
+     * is {@link PhoneAccount#SCHEME_TEL} are passed for call
+     * screening.  Further, only calls which are not in the user's contacts are passed for
+     * screening.  For outgoing calls, no post-dial digits are passed.
      *
-     * @param callDetails Information about a new incoming call, see {@link Call.Details}.
+     * @param callDetails Information about a new call, see {@link Call.Details}.
      */
     public abstract void onScreenCall(@NonNull Call.Details callDetails);
 
     /**
-     * Responds to the given call, either allowing it or disallowing it.
+     * Responds to the given incoming call, either allowing it or disallowing it.
      * <p>
      * The {@link CallScreeningService} calls this method to inform the system whether the call
      * should be silently blocked or not.
+     * <p>
+     * Calls to this method are ignored unless the {@link Call.Details#getCallDirection()} is
+     * {@link Call.Details#DIRECTION_INCOMING}.
      *
      * @param callDetails The call to allow.
      *                    <p>
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 1aeeca7..cea2fbf 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -40,11 +40,30 @@
 import java.util.List;
 
 /**
- * This service is implemented by any app that wishes to provide the user-interface for managing
- * phone calls. Telecom binds to this service while there exists a live (active or incoming) call,
- * and uses it to notify the in-call app of any live and recently disconnected calls. An app must
- * first be set as the default phone app (See {@link TelecomManager#getDefaultDialerPackage()})
- * before the telecom service will bind to its {@code InCallService} implementation.
+ * This service is implemented by an app that wishes to provide functionality for managing
+ * phone calls.
+ * <p>
+ * There are three types of apps which Telecom can bind to when there exists a live (active or
+ * incoming) call:
+ * <ol>
+ *     <li>Default Dialer/Phone app - the default dialer/phone app is one which provides the
+ *     in-call user interface while the device is in a call.  A device is bundled with a system
+ *     provided default dialer/phone app.  The user may choose a single app to take over this role
+ *     from the system app.</li>
+ *     <li>Default Car-mode Dialer/Phone app - the default car-mode dialer/phone app is one which
+ *     provides the in-call user interface while the device is in a call and the device is in car
+ *     mode.  The user may choose a single app to fill this role.</li>
+ *     <li>Call Companion app - a call companion app is one which provides no user interface itself,
+ *     but exposes call information to another display surface, such as a wearable device.  The
+ *     user may choose multiple apps to fill this role.</li>
+ * </ol>
+ * <p>
+ * Apps which wish to fulfill one of the above roles use the {@code android.app.role.RoleManager}
+ * to request that they fill the desired role.
+ *
+ * <h2>Becoming the Default Phone App</h2>
+ * An app filling the role of the default phone app provides a user interface while the device is in
+ * a call, and the device is not in car mode.
  * <p>
  * Below is an example manifest registration for an {@code InCallService}. The meta-data
  * {@link TelecomManager#METADATA_IN_CALL_SERVICE_UI} indicates that this particular
@@ -82,12 +101,34 @@
  * }
  * </pre>
  * <p>
- * When a user installs your application and runs it for the first time, you should prompt the user
- * to see if they would like your application to be the new default phone app.  See the
- * {@link TelecomManager#ACTION_CHANGE_DEFAULT_DIALER} intent documentation for more information on
- * how to do this.
+ * When a user installs your application and runs it for the first time, you should use the
+ * {@code android.app.role.RoleManager} to prompt the user to see if they would like your app to
+ * be the new default phone app.
+ * <p id="requestRole">
+ * The code below shows how your app can request to become the default phone/dialer app:
+ * <pre>
+ * {@code
+ * private static final int REQUEST_ID = 1;
+ *
+ * public void requestRole() {
+ *     RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
+ *     Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_DIALER);
+ *     startActivityForResult(intent, REQUEST_ID);
+ * }
+ *
+ * &#64;Override
+ * public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ *     if (requestCode == REQUEST_ID) {
+ *         if (resultCode == android.app.Activity.RESULT_OK) {
+ *             // Your app is now the default dialer app
+ *         } else {
+ *             // Your app is not the default dialer app
+ *         }
+ *     }
+ * }
+ * </pre>
  * <p id="incomingCallNotification">
- * <h2>Showing the Incoming Call Notification</h2>
+ * <h3>Showing the Incoming Call Notification</h3>
  * When your app receives a new incoming call via {@link InCallService#onCallAdded(Call)}, it is
  * responsible for displaying an incoming call UI for the incoming call.  It should do this using
  * {@link android.app.NotificationManager} APIs to post a new incoming call notification.
@@ -121,7 +162,7 @@
  * heads-up notification if the user is actively using the phone.  When the user is not using the
  * phone, your full-screen incoming call UI is used instead.
  * For example:
- * <pre><code>
+ * <pre><code>{@code
  * // Create an intent which triggers your fullscreen incoming call user interface.
  * Intent intent = new Intent(Intent.ACTION_MAIN, null);
  * intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -151,7 +192,49 @@
  * NotificationManager notificationManager = mContext.getSystemService(
  *     NotificationManager.class);
  * notificationManager.notify(YOUR_CHANNEL_ID, YOUR_TAG, YOUR_ID, builder.build());
- * </code></pre>
+ * }</pre>
+ * <p>
+ * <h2>Becoming the Default Car-mode Phone App</h2>
+ * An app filling the role of the default car-mode dialer/phone app provides a user interface while
+ * the device is in a call, and in car mode.  See
+ * {@link android.app.UiModeManager#ACTION_ENTER_CAR_MODE} for more information about car mode.
+ * When the device is in car mode, Telecom binds to the default car-mode dialer/phone app instead
+ * of the usual dialer/phone app.
+ * <p>
+ * Similar to the requirements for becoming the default dialer/phone app, your app must declare a
+ * manifest entry for its {@link InCallService} implementation.  Your manifest entry should ensure
+ * the following conditions are met:
+ * <ul>
+ *     <li>Do NOT declare the {@link TelecomManager#METADATA_IN_CALL_SERVICE_UI} metadata.</li>
+ *     <li>Set the {@link TelecomManager#METADATA_IN_CALL_SERVICE_CAR_MODE_UI} metadata to
+ *     {@code true}<li>
+ *     <li>Your app must request the permission
+ *     {@link android.Manifest.permission.CALL_COMPANION_APP}.</li>
+ * </ul>
+ * <p>
+ * Your app should request to fill the role {@code android.app.role.CAR_MODE_DIALER_APP} in order to
+ * become the default (see <a href="#requestRole">above</a> for how to request your app fills this
+ * role).
+ *
+ * <h2>Becoming a Call Companion App</h2>
+ * An app which fills the companion app role does not directly provide a user interface while the
+ * device is in a call.  Instead, it is typically used to relay information about calls to another
+ * display surface, such as a wearable device.
+ * <p>
+ * Similar to the requirements for becoming the default dialer/phone app, your app must declare a
+ * manifest entry for its {@link InCallService} implementation.  Your manifest entry should
+ * ensure the following conditions are met:
+ * <ul>
+ *     <li>Do NOT declare the {@link TelecomManager#METADATA_IN_CALL_SERVICE_UI} metadata.</li>
+ *     <li>Do NOT declare the {@link TelecomManager#METADATA_IN_CALL_SERVICE_CAR_MODE_UI}
+ *     metadata.</li>
+ *     <li>Your app must request the permission
+ *     {@link android.Manifest.permission.CALL_COMPANION_APP}.</li>
+ * </ul>
+ * <p>
+ * Your app should request to fill the role {@code android.app.role.CALL_COMPANION_APP} in order to
+ * become a call companion app (see <a href="#requestRole">above</a> for how to request your app
+ * fills this role).
  */
 public abstract class InCallService extends Service {
 
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index 911786e..f7dec83 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -24,6 +24,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
+import android.telecom.Call.Details.CallDirection;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -64,6 +65,7 @@
     private final Bundle mExtras;
     private final long mCreationTimeMillis;
     private final CallIdentification mCallIdentification;
+    private final int mCallDirection;
 
     public ParcelableCall(
             String id,
@@ -92,7 +94,8 @@
             Bundle intentExtras,
             Bundle extras,
             long creationTimeMillis,
-            CallIdentification callIdentification) {
+            CallIdentification callIdentification,
+            int callDirection) {
         mId = id;
         mState = state;
         mDisconnectCause = disconnectCause;
@@ -120,6 +123,7 @@
         mExtras = extras;
         mCreationTimeMillis = creationTimeMillis;
         mCallIdentification = callIdentification;
+        mCallDirection = callDirection;
     }
 
     /** The unique ID of the call. */
@@ -318,6 +322,13 @@
         return mCallIdentification;
     }
 
+    /**
+     * Indicates whether the call is an incoming or outgoing call.
+     */
+    public @CallDirection int getCallDirection() {
+        return mCallDirection;
+    }
+
     /** Responsible for creating ParcelableCall objects for deserialized Parcels. */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public static final Parcelable.Creator<ParcelableCall> CREATOR =
@@ -356,6 +367,7 @@
             ParcelableRttCall rttCall = source.readParcelable(classLoader);
             long creationTimeMillis = source.readLong();
             CallIdentification callIdentification = source.readParcelable(classLoader);
+            int callDirection = source.readInt();
             return new ParcelableCall(
                     id,
                     state,
@@ -383,7 +395,8 @@
                     intentExtras,
                     extras,
                     creationTimeMillis,
-                    callIdentification);
+                    callIdentification,
+                    callDirection);
         }
 
         @Override
@@ -429,6 +442,7 @@
         destination.writeParcelable(mRttCall, 0);
         destination.writeLong(mCreationTimeMillis);
         destination.writeParcelable(mCallIdentification, 0);
+        destination.writeInt(mCallDirection);
     }
 
     @Override
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index c3e80b4..94ed7c3 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1397,8 +1397,14 @@
      *
      * @return {@code true} if there is a call which will be rejected or terminated, {@code false}
      * otherwise.
+     * @deprecated Companion apps for wearable devices should use the {@link InCallService} API
+     * instead.  Apps performing call screening should use the {@link CallScreeningService} API
+     * instead.
      */
+
+
     @RequiresPermission(Manifest.permission.ANSWER_PHONE_CALLS)
+    @Deprecated
     public boolean endCall() {
         try {
             if (isServiceConnected()) {
@@ -1419,11 +1425,15 @@
      *
      * Requires permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE} or
      * {@link android.Manifest.permission#ANSWER_PHONE_CALLS}
+     *
+     * @deprecated Companion apps for wearable devices should use the {@link InCallService} API
+     * instead.
      */
     //TODO: L-release - need to convert all invocation of ITelecmmService#answerRingingCall to use
     // this method (clockwork & gearhead).
     @RequiresPermission(anyOf =
             {Manifest.permission.ANSWER_PHONE_CALLS, Manifest.permission.MODIFY_PHONE_STATE})
+    @Deprecated
     public void acceptRingingCall() {
         try {
             if (isServiceConnected()) {
@@ -1442,9 +1452,12 @@
      * {@link android.Manifest.permission#ANSWER_PHONE_CALLS}
      *
      * @param videoState The desired video state to answer the call with.
+     * @deprecated Companion apps for wearable devices should use the {@link InCallService} API
+     * instead.
      */
     @RequiresPermission(anyOf =
             {Manifest.permission.ANSWER_PHONE_CALLS, Manifest.permission.MODIFY_PHONE_STATE})
+    @Deprecated
     public void acceptRingingCall(int videoState) {
         try {
             if (isServiceConnected()) {
diff --git a/telephony/java/android/telephony/CallAttributes.java b/telephony/java/android/telephony/CallAttributes.java
index 2d29875..a4cce9c 100644
--- a/telephony/java/android/telephony/CallAttributes.java
+++ b/telephony/java/android/telephony/CallAttributes.java
@@ -50,10 +50,9 @@
     }
 
     private CallAttributes(Parcel in) {
-        mPreciseCallState = (PreciseCallState)
-                in.readValue(PreciseCallState.class.getClassLoader());
-        mNetworkType = in.readInt();
-        mCallQuality = (CallQuality) in.readValue(CallQuality.class.getClassLoader());
+        this.mPreciseCallState = in.readParcelable(PreciseCallState.class.getClassLoader());
+        this.mNetworkType = in.readInt();
+        this.mCallQuality = in.readParcelable(CallQuality.class.getClassLoader());
     }
 
     // getters
@@ -134,9 +133,9 @@
      * {@link Parcelable#writeToParcel}
      */
     public void writeToParcel(Parcel dest, @Parcelable.WriteFlags int flags) {
-        mPreciseCallState.writeToParcel(dest, flags);
+        dest.writeParcelable(mPreciseCallState, flags);
         dest.writeInt(mNetworkType);
-        mCallQuality.writeToParcel(dest, flags);
+        dest.writeParcelable(mCallQuality, flags);
     }
 
     public static final Parcelable.Creator<CallAttributes> CREATOR = new Parcelable.Creator() {
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index 061cd4b..6f84ec5 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -77,6 +77,14 @@
     }
 
     /**
+     * @hide
+     * @param ss signal strength from modem.
+     */
+    public CellSignalStrengthNr(android.hardware.radio.V1_4.NrSignalStrength ss) {
+        this(ss.csiRsrp, ss.csiRsrq, ss.csiSinr, ss.ssRsrp, ss.ssRsrq, ss.ssSinr);
+    }
+
+    /**
      * Reference: 3GPP TS 38.215.
      * Range: -140 dBm to -44 dBm.
      * @return SS reference signal received power, {@link CellInfo#UNAVAILABLE} means unreported
diff --git a/telephony/java/android/telephony/NetworkService.java b/telephony/java/android/telephony/NetworkService.java
index 4bca404..6c45cc4 100644
--- a/telephony/java/android/telephony/NetworkService.java
+++ b/telephony/java/android/telephony/NetworkService.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
@@ -112,13 +113,13 @@
                     mSlotId, 0, null).sendToTarget();
         }
 
-        private void registerForStateChanged(INetworkServiceCallback callback) {
+        private void registerForStateChanged(@NonNull INetworkServiceCallback callback) {
             synchronized (mNetworkRegistrationStateChangedCallbacks) {
                 mNetworkRegistrationStateChangedCallbacks.add(callback);
             }
         }
 
-        private void unregisterForStateChanged(INetworkServiceCallback callback) {
+        private void unregisterForStateChanged(@NonNull INetworkServiceCallback callback) {
             synchronized (mNetworkRegistrationStateChangedCallbacks) {
                 mNetworkRegistrationStateChangedCallbacks.remove(callback);
             }
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index af324de..fea1b7b 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -28,6 +28,7 @@
 import android.os.HandlerExecutor;
 import android.os.Looper;
 import android.telephony.emergency.EmergencyNumber;
+import android.telephony.ims.ImsReasonInfo;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.IPhoneStateListener;
@@ -347,6 +348,20 @@
     @SystemApi
     public static final int LISTEN_CALL_ATTRIBUTES_CHANGED                 = 0x04000000;
 
+    /**
+     * Listen for IMS call disconnect causes which contains
+     * {@link android.telephony.ims.ImsReasonInfo}
+     *
+     * {@more}
+     * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+     * READ_PRECISE_PHONE_STATE}
+     *
+     * @see #onImsCallDisconnectCauseChanged(ImsReasonInfo)
+     * @hide
+     */
+    @SystemApi
+    public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES              = 0x08000000;
+
     /*
      * Subscription used to listen to the phone state changes
      * @hide
@@ -578,6 +593,17 @@
     }
 
     /**
+     * Callback invoked when Ims call disconnect cause changes.
+     * @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed.
+     *
+     * @hide
+     */
+    @SystemApi
+    public void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo) {
+        // default implementation empty
+    }
+
+    /**
      * Callback invoked when data connection state changes with precise information.
      * @param dataConnectionState {@link PreciseDataConnectionState}
      *
@@ -981,6 +1007,16 @@
             Binder.withCleanCallingIdentity(
                     () -> mExecutor.execute(() -> psl.onPreferredDataSubIdChanged(subId)));
         }
+
+        public void onImsCallDisconnectCauseChanged(ImsReasonInfo disconnectCause) {
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onImsCallDisconnectCauseChanged(disconnectCause)));
+
+        }
     }
 
 
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index f63b753..0d94c4d 100644
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -57,6 +57,9 @@
     public static final int RAF_LTE = TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
     public static final int RAF_LTE_CA = TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
 
+    // 5G
+    public static final int RAF_NR = TelephonyManager.NETWORK_TYPE_BITMASK_NR;
+
     // Grouping of RAFs
     // 2G
     private static final int GSM = RAF_GSM | RAF_GPRS | RAF_EDGE;
@@ -68,6 +71,9 @@
     // 4G
     private static final int LTE = RAF_LTE | RAF_LTE_CA;
 
+    // 5G
+    private static final int NR = RAF_NR;
+
     /* Phone ID of phone */
     private int mPhoneId;
 
@@ -160,84 +166,78 @@
 
     @UnsupportedAppUsage
     public static int getRafFromNetworkType(int type) {
-        int raf;
-
         switch (type) {
             case RILConstants.NETWORK_MODE_WCDMA_PREF:
-                raf = GSM | WCDMA;
-                break;
+                return GSM | WCDMA;
             case RILConstants.NETWORK_MODE_GSM_ONLY:
-                raf = GSM;
-                break;
+                return GSM;
             case RILConstants.NETWORK_MODE_WCDMA_ONLY:
-                raf = WCDMA;
-                break;
+                return WCDMA;
             case RILConstants.NETWORK_MODE_GSM_UMTS:
-                raf = GSM | WCDMA;
-                break;
+                return GSM | WCDMA;
             case RILConstants.NETWORK_MODE_CDMA:
-                raf = CDMA | EVDO;
-                break;
+                return CDMA | EVDO;
             case RILConstants.NETWORK_MODE_LTE_CDMA_EVDO:
-                raf = LTE | CDMA | EVDO;
-                break;
+                return LTE | CDMA | EVDO;
             case RILConstants.NETWORK_MODE_LTE_GSM_WCDMA:
-                raf = LTE | GSM | WCDMA;
-                break;
+                return LTE | GSM | WCDMA;
             case RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
-                raf = LTE | CDMA | EVDO | GSM | WCDMA;
-                break;
+                return LTE | CDMA | EVDO | GSM | WCDMA;
             case RILConstants.NETWORK_MODE_LTE_ONLY:
-                raf = LTE;
-                break;
+                return LTE;
             case RILConstants.NETWORK_MODE_LTE_WCDMA:
-                raf = LTE | WCDMA;
-                break;
+                return LTE | WCDMA;
             case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
-                raf = CDMA;
-                break;
+                return CDMA;
             case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
-                raf = EVDO;
-                break;
+                return EVDO;
             case RILConstants.NETWORK_MODE_GLOBAL:
-                raf = GSM | WCDMA | CDMA | EVDO;
-                break;
+                return GSM | WCDMA | CDMA | EVDO;
             case RILConstants.NETWORK_MODE_TDSCDMA_ONLY:
-                raf = RAF_TD_SCDMA;
-                break;
+                return RAF_TD_SCDMA;
             case RILConstants.NETWORK_MODE_TDSCDMA_WCDMA:
-                raf = RAF_TD_SCDMA | WCDMA;
-                break;
+                return RAF_TD_SCDMA | WCDMA;
             case RILConstants.NETWORK_MODE_LTE_TDSCDMA:
-                raf = LTE | RAF_TD_SCDMA;
-                break;
+                return LTE | RAF_TD_SCDMA;
             case RILConstants.NETWORK_MODE_TDSCDMA_GSM:
-                raf = RAF_TD_SCDMA | GSM;
-                break;
+                return RAF_TD_SCDMA | GSM;
             case RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM:
-                raf = LTE | RAF_TD_SCDMA | GSM;
-                break;
+                return LTE | RAF_TD_SCDMA | GSM;
             case RILConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
-                raf = RAF_TD_SCDMA | GSM | WCDMA;
-                break;
+                return RAF_TD_SCDMA | GSM | WCDMA;
             case RILConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
-                raf = LTE | RAF_TD_SCDMA | WCDMA;
-                break;
+                return LTE | RAF_TD_SCDMA | WCDMA;
             case RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
-                raf = LTE | RAF_TD_SCDMA | GSM | WCDMA;
-                break;
+                return LTE | RAF_TD_SCDMA | GSM | WCDMA;
             case RILConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
-                raf = RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
-                break;
+                return RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
             case RILConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
-                raf = LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
-                break;
+                return LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
+            case (RILConstants.NETWORK_MODE_NR_ONLY):
+                return NR;
+            case (RILConstants.NETWORK_MODE_NR_LTE):
+                return NR | LTE;
+            case (RILConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO):
+                return NR | LTE | CDMA | EVDO;
+            case (RILConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA):
+                return NR | LTE | GSM | WCDMA;
+            case (RILConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA):
+                return NR | LTE | CDMA | EVDO | GSM | WCDMA;
+            case (RILConstants.NETWORK_MODE_NR_LTE_WCDMA):
+                return NR | LTE | WCDMA;
+            case (RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA):
+                return NR | LTE | RAF_TD_SCDMA;
+            case (RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM):
+                return NR | LTE | RAF_TD_SCDMA | GSM;
+            case (RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA):
+                return NR | LTE | RAF_TD_SCDMA | WCDMA;
+            case (RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA):
+                return NR | LTE | RAF_TD_SCDMA | GSM | WCDMA;
+            case (RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA):
+                return NR | LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
             default:
-                raf = RAF_UNKNOWN;
-                break;
+                return RAF_UNKNOWN;
         }
-
-        return raf;
     }
 
     /**
@@ -250,6 +250,7 @@
         raf = ((CDMA & raf) > 0) ? (CDMA | raf) : raf;
         raf = ((EVDO & raf) > 0) ? (EVDO | raf) : raf;
         raf = ((LTE & raf) > 0) ? (LTE | raf) : raf;
+        raf = ((NR & raf) > 0) ? (NR | raf) : raf;
 
         return raf;
     }
@@ -274,83 +275,78 @@
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public static int getNetworkTypeFromRaf(int raf) {
-        int type;
-
         raf = getAdjustedRaf(raf);
 
         switch (raf) {
             case (GSM | WCDMA):
-                type = RILConstants.NETWORK_MODE_WCDMA_PREF;
-                break;
+                return RILConstants.NETWORK_MODE_WCDMA_PREF;
             case GSM:
-                type = RILConstants.NETWORK_MODE_GSM_ONLY;
-                break;
+                return RILConstants.NETWORK_MODE_GSM_ONLY;
             case WCDMA:
-                type = RILConstants.NETWORK_MODE_WCDMA_ONLY;
-                break;
+                return RILConstants.NETWORK_MODE_WCDMA_ONLY;
             case (CDMA | EVDO):
-                type = RILConstants.NETWORK_MODE_CDMA;
-                break;
+                return RILConstants.NETWORK_MODE_CDMA;
             case (LTE | CDMA | EVDO):
-                type = RILConstants.NETWORK_MODE_LTE_CDMA_EVDO;
-                break;
+                return RILConstants.NETWORK_MODE_LTE_CDMA_EVDO;
             case (LTE | GSM | WCDMA):
-                type = RILConstants.NETWORK_MODE_LTE_GSM_WCDMA;
-                break;
+                return RILConstants.NETWORK_MODE_LTE_GSM_WCDMA;
             case (LTE | CDMA | EVDO | GSM | WCDMA):
-                type = RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA;
-                break;
+                return RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA;
             case LTE:
-                type = RILConstants.NETWORK_MODE_LTE_ONLY;
-                break;
+                return RILConstants.NETWORK_MODE_LTE_ONLY;
             case (LTE | WCDMA):
-                type = RILConstants.NETWORK_MODE_LTE_WCDMA;
-                break;
+                return RILConstants.NETWORK_MODE_LTE_WCDMA;
             case CDMA:
-                type = RILConstants.NETWORK_MODE_CDMA_NO_EVDO;
-                break;
+                return RILConstants.NETWORK_MODE_CDMA_NO_EVDO;
             case EVDO:
-                type = RILConstants.NETWORK_MODE_EVDO_NO_CDMA;
-                break;
+                return RILConstants.NETWORK_MODE_EVDO_NO_CDMA;
             case (GSM | WCDMA | CDMA | EVDO):
-                type = RILConstants.NETWORK_MODE_GLOBAL;
-                break;
+                return RILConstants.NETWORK_MODE_GLOBAL;
             case RAF_TD_SCDMA:
-                type = RILConstants.NETWORK_MODE_TDSCDMA_ONLY;
-                break;
+                return RILConstants.NETWORK_MODE_TDSCDMA_ONLY;
             case (RAF_TD_SCDMA | WCDMA):
-                type = RILConstants.NETWORK_MODE_TDSCDMA_WCDMA;
-                break;
+                return RILConstants.NETWORK_MODE_TDSCDMA_WCDMA;
             case (LTE | RAF_TD_SCDMA):
-                type = RILConstants.NETWORK_MODE_LTE_TDSCDMA;
-                break;
+                return RILConstants.NETWORK_MODE_LTE_TDSCDMA;
             case (RAF_TD_SCDMA | GSM):
-                type = RILConstants.NETWORK_MODE_TDSCDMA_GSM;
-                break;
+                return RILConstants.NETWORK_MODE_TDSCDMA_GSM;
             case (LTE | RAF_TD_SCDMA | GSM):
-                type = RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM;
-                break;
+                return RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM;
             case (RAF_TD_SCDMA | GSM | WCDMA):
-                type = RILConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA;
-                break;
+                return RILConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA;
             case (LTE | RAF_TD_SCDMA | WCDMA):
-                type = RILConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA;
-                break;
+                return RILConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA;
             case (LTE | RAF_TD_SCDMA | GSM | WCDMA):
-                type = RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA;
-                break;
+                return RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA;
             case (RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA):
-                type = RILConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
-                break;
+                return RILConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
             case (LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA):
-                type = RILConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
-                break;
+                return RILConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
+            case (NR):
+                return RILConstants.NETWORK_MODE_NR_ONLY;
+            case (NR | LTE):
+                return RILConstants.NETWORK_MODE_NR_LTE;
+            case (NR | LTE | CDMA | EVDO):
+                return RILConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO;
+            case (NR | LTE | GSM | WCDMA):
+                return RILConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA;
+            case (NR | LTE | CDMA | EVDO | GSM | WCDMA):
+                return RILConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA;
+            case (NR | LTE | WCDMA):
+                return RILConstants.NETWORK_MODE_NR_LTE_WCDMA;
+            case (NR | LTE | RAF_TD_SCDMA):
+                return RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA;
+            case (NR | LTE | RAF_TD_SCDMA | GSM):
+                return RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM;
+            case (NR | LTE | RAF_TD_SCDMA | WCDMA):
+                return RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA;
+            case (NR | LTE | RAF_TD_SCDMA | GSM | WCDMA):
+                return RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA;
+            case (NR | LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA):
+                return RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
             default:
-                type = RILConstants.PREFERRED_NETWORK_MODE ;
-                break;
+                return RILConstants.PREFERRED_NETWORK_MODE;
         }
-
-        return type;
     }
 
     public static int singleRafTypeFromString(String rafString) {
@@ -377,6 +373,7 @@
             case "EVDO":    return EVDO;
             case "WCDMA":   return WCDMA;
             case "LTE_CA":  return RAF_LTE_CA;
+            case "NR":      return RAF_NR;
             default:        return RAF_UNKNOWN;
         }
     }
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 4475630..3317876 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -540,7 +540,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @UnsupportedAppUsage
     public int getDataRegState() {
         return mDataRegState;
     }
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 91375bc..d2ae106 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -85,6 +85,7 @@
     CellSignalStrengthWcdma mWcdma;
     CellSignalStrengthTdscdma mTdscdma;
     CellSignalStrengthLte mLte;
+    CellSignalStrengthNr mNr;
 
     /**
      * Create a new SignalStrength from a intent notifier Bundle
@@ -116,7 +117,7 @@
     public SignalStrength() {
         this(new CellSignalStrengthCdma(), new CellSignalStrengthGsm(),
                 new CellSignalStrengthWcdma(), new CellSignalStrengthTdscdma(),
-                new CellSignalStrengthLte());
+                new CellSignalStrengthLte(), new CellSignalStrengthNr());
     }
 
     /**
@@ -129,12 +130,14 @@
             @NonNull CellSignalStrengthGsm gsm,
             @NonNull CellSignalStrengthWcdma wcdma,
             @NonNull CellSignalStrengthTdscdma tdscdma,
-            @NonNull CellSignalStrengthLte lte) {
+            @NonNull CellSignalStrengthLte lte,
+            @NonNull CellSignalStrengthNr nr) {
         mCdma = cdma;
         mGsm = gsm;
         mWcdma = wcdma;
         mTdscdma = tdscdma;
         mLte = lte;
+        mNr = nr;
     }
 
     /**
@@ -147,7 +150,8 @@
                 new CellSignalStrengthGsm(signalStrength.gw),
                 new CellSignalStrengthWcdma(),
                 new CellSignalStrengthTdscdma(signalStrength.tdScdma),
-                new CellSignalStrengthLte(signalStrength.lte));
+                new CellSignalStrengthLte(signalStrength.lte),
+                new CellSignalStrengthNr());
     }
 
     /**
@@ -160,7 +164,23 @@
                 new CellSignalStrengthGsm(signalStrength.gsm),
                 new CellSignalStrengthWcdma(signalStrength.wcdma),
                 new CellSignalStrengthTdscdma(signalStrength.tdScdma),
-                new CellSignalStrengthLte(signalStrength.lte));
+                new CellSignalStrengthLte(signalStrength.lte),
+                new CellSignalStrengthNr());
+    }
+
+    /**
+     * Constructor for Radio HAL V1.4.
+     *
+     * @param signalStrength signal strength reported from modem.
+     * @hide
+     */
+    public SignalStrength(android.hardware.radio.V1_4.SignalStrength signalStrength) {
+        this(new CellSignalStrengthCdma(signalStrength.cdma, signalStrength.evdo),
+                new CellSignalStrengthGsm(signalStrength.gsm),
+                new CellSignalStrengthWcdma(signalStrength.wcdma),
+                new CellSignalStrengthTdscdma(signalStrength.tdscdma),
+                new CellSignalStrengthLte(signalStrength.lte),
+                new CellSignalStrengthNr(signalStrength.nr));
     }
 
     private CellSignalStrength getPrimary() {
@@ -171,6 +191,7 @@
         if (mTdscdma.isValid()) return mTdscdma;
         if (mWcdma.isValid()) return mWcdma;
         if (mGsm.isValid()) return mGsm;
+        if (mNr.isValid()) return mNr;
         return mLte;
     }
 
@@ -200,6 +221,7 @@
         if (mTdscdma.isValid()) cssList.add(mTdscdma);
         if (mWcdma.isValid()) cssList.add(mWcdma);
         if (mGsm.isValid()) cssList.add(mGsm);
+        if (mNr.isValid()) cssList.add(mNr);
         return cssList;
     }
 
@@ -210,6 +232,7 @@
         mWcdma.updateLevel(cc, ss);
         mTdscdma.updateLevel(cc, ss);
         mLte.updateLevel(cc, ss);
+        mNr.updateLevel(cc, ss);
     }
 
     /**
@@ -234,6 +257,7 @@
         mWcdma = new CellSignalStrengthWcdma(s.mWcdma);
         mTdscdma = new CellSignalStrengthTdscdma(s.mTdscdma);
         mLte = new CellSignalStrengthLte(s.mLte);
+        mNr = new CellSignalStrengthNr(s.mNr);
     }
 
     /**
@@ -250,6 +274,7 @@
         mWcdma = in.readParcelable(CellSignalStrengthWcdma.class.getClassLoader());
         mTdscdma = in.readParcelable(CellSignalStrengthTdscdma.class.getClassLoader());
         mLte = in.readParcelable(CellSignalStrengthLte.class.getClassLoader());
+        mNr = in.readParcelable(CellSignalStrengthLte.class.getClassLoader());
     }
 
     /**
@@ -261,6 +286,7 @@
         out.writeParcelable(mWcdma, flags);
         out.writeParcelable(mTdscdma, flags);
         out.writeParcelable(mLte, flags);
+        out.writeParcelable(mNr, flags);
     }
 
     /**
@@ -814,7 +840,7 @@
      */
     @Override
     public int hashCode() {
-        return Objects.hash(mCdma, mGsm, mWcdma, mTdscdma, mLte);
+        return Objects.hash(mCdma, mGsm, mWcdma, mTdscdma, mLte, mNr);
     }
 
     /**
@@ -830,7 +856,8 @@
             && mGsm.equals(s.mGsm)
             && mWcdma.equals(s.mWcdma)
             && mTdscdma.equals(s.mTdscdma)
-            && mLte.equals(s.mLte);
+            && mLte.equals(s.mLte)
+            && mNr.equals(s.mNr);
     }
 
     /**
@@ -844,6 +871,7 @@
             .append(",mWcdma=").append(mWcdma)
             .append(",mTdscdma=").append(mTdscdma)
             .append(",mLte=").append(mLte)
+            .append(",mNr=").append(mNr)
             .append(",primary=").append(getPrimary().getClass().getSimpleName())
             .append("}")
             .toString();
@@ -866,6 +894,7 @@
         mWcdma = m.getParcelable("Wcdma");
         mTdscdma = m.getParcelable("Tdscdma");
         mLte = m.getParcelable("Lte");
+        mNr = m.getParcelable("Nr");
     }
 
     /**
@@ -885,6 +914,7 @@
         m.putParcelable("Wcdma", mWcdma);
         m.putParcelable("Tdscdma", mTdscdma);
         m.putParcelable("Lte", mLte);
+        m.putParcelable("Nr", mNr);
     }
 
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index f2c03ed..d857fd0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -349,41 +349,30 @@
      * Returns 0 if none of voice, sms, data is not supported
      * Returns 1 for Single standby mode (Single SIM functionality)
      * Returns 2 for Dual standby mode.(Dual SIM functionality)
+     * Returns 3 for Tri standby mode.(Tri SIM functionality)
      */
     public int getPhoneCount() {
-        int phoneCount = 1;
-        switch (getMultiSimConfiguration()) {
-            case UNKNOWN:
-                // if voice or sms or data is supported, return 1 otherwise 0
-                if (isVoiceCapable() || isSmsCapable()) {
-                    phoneCount = 1;
-                } else {
-                    // todo: try to clean this up further by getting rid of the nested conditions
-                    if (mContext == null) {
-                        phoneCount = 1;
-                    } else {
-                        // check for data support
-                        ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
-                                Context.CONNECTIVITY_SERVICE);
-                        if (cm == null) {
-                            phoneCount = 1;
-                        } else {
-                            if (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)) {
-                                phoneCount = 1;
-                            } else {
-                                phoneCount = 0;
-                            }
-                        }
-                    }
+        int phoneCount = 0;
+
+        // check for voice and data support, 0 if not supported
+        if (!isVoiceCapable() && !isSmsCapable()) {
+            ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
+                    Context.CONNECTIVITY_SERVICE);
+            if (cm != null) {
+                if (!cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)) {
+                    return phoneCount;
                 }
-                break;
-            case DSDS:
-            case DSDA:
-                phoneCount = PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM;
-                break;
-            case TSTS:
-                phoneCount = PhoneConstants.MAX_PHONE_COUNT_TRI_SIM;
-                break;
+            }
+        }
+
+        phoneCount = 1;
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                phoneCount = telephony.getNumOfActiveSims();
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "getNumOfActiveSims RemoteException", ex);
         }
         return phoneCount;
     }
@@ -6247,197 +6236,258 @@
             NETWORK_MODE_LTE_TDSCDMA_WCDMA,
             NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA,
             NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA,
-            NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA
+            NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA,
+            NETWORK_MODE_NR_ONLY,
+            NETWORK_MODE_NR_LTE,
+            NETWORK_MODE_NR_LTE_CDMA_EVDO,
+            NETWORK_MODE_NR_LTE_GSM_WCDMA,
+            NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA,
+            NETWORK_MODE_NR_LTE_WCDMA,
+            NETWORK_MODE_NR_LTE_TDSCDMA,
+            NETWORK_MODE_NR_LTE_TDSCDMA_GSM,
+            NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA,
+            NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA,
+            NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface PrefNetworkMode{}
 
     /**
-     * network mode is GSM/WCDMA (WCDMA preferred).
+     * Preferred network mode is GSM/WCDMA (WCDMA preferred).
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_WCDMA_PREF = RILConstants.NETWORK_MODE_WCDMA_PREF;
 
     /**
-     * network mode is GSM only.
+     * Preferred network mode is GSM only.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_GSM_ONLY = RILConstants.NETWORK_MODE_GSM_ONLY;
 
     /**
-     * network mode is WCDMA only.
+     * Preferred network mode is WCDMA only.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_WCDMA_ONLY = RILConstants.NETWORK_MODE_WCDMA_ONLY;
 
     /**
-     * network mode is GSM/WCDMA (auto mode, according to PRL).
+     * Preferred network mode is GSM/WCDMA (auto mode, according to PRL).
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_GSM_UMTS = RILConstants.NETWORK_MODE_GSM_UMTS;
 
     /**
-     * network mode is CDMA and EvDo (auto mode, according to PRL).
+     * Preferred network mode is CDMA and EvDo (auto mode, according to PRL).
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_CDMA_EVDO = RILConstants.NETWORK_MODE_CDMA;
 
     /**
-     * network mode is CDMA only.
+     * Preferred network mode is CDMA only.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_CDMA_NO_EVDO = RILConstants.NETWORK_MODE_CDMA_NO_EVDO;
 
     /**
-     * network mode is EvDo only.
+     * Preferred network mode is EvDo only.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_EVDO_NO_CDMA = RILConstants.NETWORK_MODE_EVDO_NO_CDMA;
 
     /**
-     * network mode is GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL).
+     * Preferred network mode is GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL).
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_GLOBAL = RILConstants.NETWORK_MODE_GLOBAL;
 
     /**
-     * network mode is LTE, CDMA and EvDo.
+     * Preferred network mode is LTE, CDMA and EvDo.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_LTE_CDMA_EVDO = RILConstants.NETWORK_MODE_LTE_CDMA_EVDO;
 
     /**
-     * preferred network mode is LTE, GSM/WCDMA.
+     * Preferred network mode is LTE, GSM/WCDMA.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_LTE_GSM_WCDMA = RILConstants.NETWORK_MODE_LTE_GSM_WCDMA;
 
     /**
-     * network mode is LTE, CDMA, EvDo, GSM/WCDMA.
+     * Preferred network mode is LTE, CDMA, EvDo, GSM/WCDMA.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA =
             RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA;
 
     /**
-     * network mode is LTE Only.
+     * Preferred network mode is LTE Only.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_LTE_ONLY = RILConstants.NETWORK_MODE_LTE_ONLY;
 
     /**
-     * network mode is LTE/WCDMA.
+     * Preferred network mode is LTE/WCDMA.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_LTE_WCDMA = RILConstants.NETWORK_MODE_LTE_WCDMA;
 
     /**
-     * network mode is TD-SCDMA only.
+     * Preferred network mode is TD-SCDMA only.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_TDSCDMA_ONLY = RILConstants.NETWORK_MODE_TDSCDMA_ONLY;
 
     /**
-     * network mode is TD-SCDMA and WCDMA.
+     * Preferred network mode is TD-SCDMA and WCDMA.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_TDSCDMA_WCDMA = RILConstants.NETWORK_MODE_TDSCDMA_WCDMA;
 
     /**
-     * network mode is TD-SCDMA and LTE.
+     * Preferred network mode is TD-SCDMA and LTE.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_LTE_TDSCDMA = RILConstants.NETWORK_MODE_LTE_TDSCDMA;
 
     /**
-     * network mode is TD-SCDMA and GSM.
+     * Preferred network mode is TD-SCDMA and GSM.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_TDSCDMA_GSM = RILConstants.NETWORK_MODE_TDSCDMA_GSM;
 
     /**
-     * network mode is TD-SCDMA,GSM and LTE.
+     * Preferred network mode is TD-SCDMA,GSM and LTE.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_LTE_TDSCDMA_GSM =
             RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM;
 
     /**
-     * network mode is TD-SCDMA, GSM/WCDMA.
+     * Preferred network mode is TD-SCDMA, GSM/WCDMA.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_TDSCDMA_GSM_WCDMA =
             RILConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA;
 
     /**
-     * network mode is TD-SCDMA, WCDMA and LTE.
+     * Preferred network mode is TD-SCDMA, WCDMA and LTE.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_LTE_TDSCDMA_WCDMA =
             RILConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA;
 
     /**
-     * network mode is TD-SCDMA, GSM/WCDMA and LTE.
+     * Preferred network mode is TD-SCDMA, GSM/WCDMA and LTE.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA =
             RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA;
 
     /**
-     * network mode is TD-SCDMA,EvDo,CDMA,GSM/WCDMA.
+     * Preferred network mode is TD-SCDMA,EvDo,CDMA,GSM/WCDMA.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA =
             RILConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
-
     /**
-     * network mode is TD-SCDMA/LTE/GSM/WCDMA, CDMA, and EvDo.
+     * Preferred network mode is TD-SCDMA/LTE/GSM/WCDMA, CDMA, and EvDo.
      * @hide
      */
-    @SystemApi
     public static final int NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA =
             RILConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
 
     /**
+     * Preferred network mode is NR 5G only.
+     * @hide
+     */
+    public static final int NETWORK_MODE_NR_ONLY = RILConstants.NETWORK_MODE_NR_ONLY;
+
+    /**
+     * Preferred network mode is NR 5G, LTE.
+     * @hide
+     */
+    public static final int NETWORK_MODE_NR_LTE = RILConstants.NETWORK_MODE_NR_LTE;
+
+    /**
+     * Preferred network mode is NR 5G, LTE, CDMA and EvDo.
+     * @hide
+     */
+    public static final int NETWORK_MODE_NR_LTE_CDMA_EVDO =
+            RILConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO;
+
+    /**
+     * Preferred network mode is NR 5G, LTE, GSM and WCDMA.
+     * @hide
+     */
+    public static final int NETWORK_MODE_NR_LTE_GSM_WCDMA =
+            RILConstants.NETWORK_MODE_NR_LTE_GSM_WCDMA;
+
+    /**
+     * Preferred network mode is NR 5G, LTE, CDMA, EvDo, GSM and WCDMA.
+     * @hide
+     */
+    public static final int NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA =
+            RILConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA;
+
+    /**
+     * Preferred network mode is NR 5G, LTE and WCDMA.
+     * @hide
+     */
+    public static final int NETWORK_MODE_NR_LTE_WCDMA = RILConstants.NETWORK_MODE_NR_LTE_WCDMA;
+
+    /**
+     * Preferred network mode is NR 5G, LTE and TDSCDMA.
+     * @hide
+     */
+    public static final int NETWORK_MODE_NR_LTE_TDSCDMA = RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA;
+
+    /**
+     * Preferred network mode is NR 5G, LTE, TD-SCDMA and GSM.
+     * @hide
+     */
+    public static final int NETWORK_MODE_NR_LTE_TDSCDMA_GSM =
+            RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM;
+
+    /**
+     * Preferred network mode is NR 5G, LTE, TD-SCDMA, WCDMA.
+     * @hide
+     */
+    public static final int NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA =
+            RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA;
+
+    /**
+     * Preferred network mode is NR 5G, LTE, TD-SCDMA, GSM and WCDMA.
+     * @hide
+     */
+    public static final int NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA =
+            RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA;
+
+    /**
+     * Preferred network mode is NR 5G, LTE, TD-SCDMA, CDMA, EVDO, GSM and WCDMA.
+     * @hide
+     */
+    public static final int NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA =
+            RILConstants.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
+
+    /**
      * Get the preferred network type.
      * Used for device configuration by some CDMA operators.
      *
      * <p>Requires Permission:
-     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
      * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @return the preferred network type.
      * @hide
      */
-    @RequiresPermission((android.Manifest.permission.MODIFY_PHONE_STATE))
-    @SystemApi
+    @RequiresPermission((android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE))
+    @UnsupportedAppUsage
     public @PrefNetworkMode int getPreferredNetworkType(int subId) {
         try {
             ITelephony telephony = getITelephony();
-            if (telephony != null)
+            if (telephony != null) {
                 return telephony.getPreferredNetworkType(subId);
+            }
         } catch (RemoteException ex) {
             Rlog.e(TAG, "getPreferredNetworkType RemoteException", ex);
         } catch (NullPointerException ex) {
@@ -9979,4 +10029,120 @@
         }
         return ret;
     }
+
+    /**
+     * Indicate if the user is allowed to use multiple SIM cards at the same time to register
+     * on the network (e.g. Dual Standby or Dual Active) when the device supports it, or if the
+     * usage is restricted. This API is used to prevent usage of multiple SIM card, based on
+     * policies of the carrier.
+     * <p>Note: the API does not prevent access to the SIM cards for operations that don't require
+     * access to the network.
+     *
+     * @param isMultisimCarrierRestricted true if usage of multiple SIMs is restricted, false
+     * otherwise.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setMultisimCarrierRestriction(boolean isMultisimCarrierRestricted) {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                service.setMultisimCarrierRestriction(isMultisimCarrierRestricted);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "setMultisimCarrierRestriction RemoteException", e);
+        }
+    }
+
+    /**
+     * Returns if the usage of multiple SIM cards at the same time to register on the network
+     * (e.g. Dual Standby or Dual Active) is restricted.
+     *
+     * @return true if usage of multiple SIMs is restricted, false otherwise.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public boolean isMultisimCarrierRestricted() {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.isMultisimCarrierRestricted();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "isMultisimCarrierRestricted RemoteException", e);
+        }
+        return true;
+    }
+
+    /**
+     * Broadcast intent action for network country code changes.
+     *
+     * <p>
+     * The {@link #EXTRA_NETWORK_COUNTRY} extra indicates the country code of the current
+     * network returned by {@link #getNetworkCountryIso()}.
+     *
+     * @see #EXTRA_NETWORK_COUNTRY
+     * @see #getNetworkCountryIso()
+     */
+    public static final String ACTION_NETWORK_COUNTRY_CHANGED =
+            "android.telephony.action.NETWORK_COUNTRY_CHANGED";
+
+    /**
+     * The extra used with an {@link #ACTION_NETWORK_COUNTRY_CHANGED} to specify the
+     * the country code in ISO 3166 format.
+     * <p class="note">
+     * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
+     */
+    public static final String EXTRA_NETWORK_COUNTRY =
+            "android.telephony.extra.NETWORK_COUNTRY";
+    /**
+     * Switch configs to enable multi-sim or switch back to single-sim
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+     * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * @param numOfSims number of live SIMs we want to switch to
+     * @throws android.os.RemoteException
+     */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void switchMultiSimConfig(int numOfSims) {
+        //only proceed if multi-sim is not restricted
+        if (isMultisimCarrierRestricted()) {
+            Rlog.e(TAG, "switchMultiSimConfig not possible. It is restricted.");
+            return;
+        }
+
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.switchMultiSimConfig(numOfSims);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "switchMultiSimConfig RemoteException", ex);
+        }
+    }
+
+    /**
+     * Get whether reboot is required or not after making changes to modem configurations.
+     * @Return {@code True} if reboot is required after making changes to modem configurations,
+     * otherwise return {@code False}.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public boolean isRebootRequiredForModemConfigChange() {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.isRebootRequiredForModemConfigChange();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "isRebootRequiredForModemConfigChange RemoteException", e);
+        }
+        return false;
+    }
 }
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 74d1e83..79572b9 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -157,7 +157,10 @@
                                   @Nullable LinkProperties linkProperties,
                                   @Nullable DataServiceCallback callback) {
             // The default implementation is to return unsupported.
-            callback.onSetupDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, null);
+            if (callback != null) {
+                callback.onSetupDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED,
+                        null);
+            }
         }
 
         /**
@@ -176,7 +179,9 @@
         public void deactivateDataCall(int cid, @DeactivateDataReason int reason,
                                        @Nullable DataServiceCallback callback) {
             // The default implementation is to return unsupported.
-            callback.onDeactivateDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+            if (callback != null) {
+                callback.onDeactivateDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+            }
         }
 
         /**
@@ -190,7 +195,10 @@
         public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming,
                                         @Nullable DataServiceCallback callback) {
             // The default implementation is to return unsupported.
-            callback.onSetInitialAttachApnComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+            if (callback != null) {
+                callback.onSetInitialAttachApnComplete(
+                        DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+            }
         }
 
         /**
@@ -206,7 +214,9 @@
         public void setDataProfile(List<DataProfile> dps, boolean isRoaming,
                                    @Nullable DataServiceCallback callback) {
             // The default implementation is to return unsupported.
-            callback.onSetDataProfileComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+            if (callback != null) {
+                callback.onSetDataProfileComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
+            }
         }
 
         /**
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index a5c0442..40c6f70 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -253,7 +253,7 @@
     public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5;
 
     private final Context mContext;
-    private final int mCardId;
+    private int mCardId;
 
     /** @hide */
     public EuiccManager(Context context) {
@@ -291,7 +291,7 @@
     public boolean isEnabled() {
         // In the future, this may reach out to IEuiccController (if non-null) to check any dynamic
         // restrictions.
-        return getIEuiccController() != null && mCardId != TelephonyManager.INVALID_CARD_ID;
+        return getIEuiccController() != null;
     }
 
     /**
@@ -301,15 +301,15 @@
      * current eUICC. A calling app with carrier privileges for one eUICC may not necessarily have
      * access to the EID of another eUICC.
      *
-     * @return the EID. May be null if {@link #isEnabled()} is false or the eUICC is not ready.
+     * @return the EID. May be null if the eUICC is not ready.
      */
     @Nullable
     public String getEid() {
-        if (!isEnabled()) {
+        if (!refreshCardIdIfInvalid()) {
             return null;
         }
         try {
-            return getIEuiccController().getEid(mCardId);
+            return getIEuiccController().getEid(mCardId, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -320,15 +320,15 @@
      *
      * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
      *
-     * @return the status of eUICC OTA. If {@link #isEnabled()} is false or the eUICC is not ready,
-     *     {@link OtaStatus#EUICC_OTA_STATUS_UNAVAILABLE} will be returned.
+     * @return the status of eUICC OTA. If the eUICC is not ready,
+     *         {@link OtaStatus#EUICC_OTA_STATUS_UNAVAILABLE} will be returned.
      *
      * @hide
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public int getOtaStatus() {
-        if (!isEnabled()) {
+        if (!refreshCardIdIfInvalid()) {
             return EUICC_OTA_STATUS_UNAVAILABLE;
         }
         try {
@@ -347,6 +347,15 @@
      * Without the former, an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be
      * returned in the callback intent to prompt the user to accept the download.
      *
+     * <p>On a multi-active SIM device, requires the
+     * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, or a calling app
+     * only if the targeted eUICC does not currently have an active subscription or the calling app
+     * is authorized to manage the active subscription on the target eUICC, and the calling app is
+     * authorized to manage any active subscription on any SIM. Without it, an
+     * {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
+     * intent to prompt the user to accept the download. The caller should also be authorized to
+     * manage the subscription to be downloaded.
+     *
      * @param subscription the subscription to download.
      * @param switchAfterDownload if true, the profile will be activated upon successful download.
      * @param callbackIntent a PendingIntent to launch when the operation completes.
@@ -354,7 +363,7 @@
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void downloadSubscription(DownloadableSubscription subscription,
             boolean switchAfterDownload, PendingIntent callbackIntent) {
-        if (!isEnabled()) {
+        if (!refreshCardIdIfInvalid()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -416,7 +425,7 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void continueOperation(Intent resolutionIntent, Bundle resolutionExtras) {
-        if (!isEnabled()) {
+        if (!refreshCardIdIfInvalid()) {
             PendingIntent callbackIntent =
                     resolutionIntent.getParcelableExtra(
                             EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT);
@@ -453,7 +462,7 @@
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void getDownloadableSubscriptionMetadata(
             DownloadableSubscription subscription, PendingIntent callbackIntent) {
-        if (!isEnabled()) {
+        if (!refreshCardIdIfInvalid()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -483,7 +492,7 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void getDefaultDownloadableSubscriptionList(PendingIntent callbackIntent) {
-        if (!isEnabled()) {
+        if (!refreshCardIdIfInvalid()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -498,12 +507,11 @@
     /**
      * Returns information about the eUICC chip/device.
      *
-     * @return the {@link EuiccInfo}. May be null if {@link #isEnabled()} is false or the eUICC is
-     *     not ready.
+     * @return the {@link EuiccInfo}. May be null if the eUICC is not ready.
      */
     @Nullable
     public EuiccInfo getEuiccInfo() {
-        if (!isEnabled()) {
+        if (!refreshCardIdIfInvalid()) {
             return null;
         }
         try {
@@ -528,7 +536,7 @@
      */
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void deleteSubscription(int subscriptionId, PendingIntent callbackIntent) {
-        if (!isEnabled()) {
+        if (!refreshCardIdIfInvalid()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -549,14 +557,26 @@
      * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
      * intent to prompt the user to accept the download.
      *
+     * <p>On a multi-active SIM device, requires the
+     * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, or a calling app
+     *  only if the targeted eUICC does not currently have an active subscription or the calling app
+     * is authorized to manage the active subscription on the target eUICC, and the calling app is
+     * authorized to manage any active subscription on any SIM. Without it, an
+     * {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
+     * intent to prompt the user to accept the download. The caller should also be authorized to
+     * manage the subscription to be enabled.
+     *
      * @param subscriptionId the ID of the subscription to enable. May be
      *     {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID} to deactivate the
-     *     current profile without activating another profile to replace it.
+     *     current profile without activating another profile to replace it. If it's a disable
+     *     operation, requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS}
+     *     permission, or the calling app must be authorized to manage the active subscription on
+     *     the target eUICC.
      * @param callbackIntent a PendingIntent to launch when the operation completes.
      */
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void switchToSubscription(int subscriptionId, PendingIntent callbackIntent) {
-        if (!isEnabled()) {
+        if (!refreshCardIdIfInvalid()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -582,7 +602,7 @@
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void updateSubscriptionNickname(
             int subscriptionId, String nickname, PendingIntent callbackIntent) {
-        if (!isEnabled()) {
+        if (!refreshCardIdIfInvalid()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -606,7 +626,7 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void eraseSubscriptions(PendingIntent callbackIntent) {
-        if (!isEnabled()) {
+        if (!refreshCardIdIfInvalid()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -636,7 +656,7 @@
      * @hide
      */
     public void retainSubscriptionsForFactoryReset(PendingIntent callbackIntent) {
-        if (!isEnabled()) {
+        if (!refreshCardIdIfInvalid()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -647,6 +667,19 @@
         }
     }
 
+    private boolean refreshCardIdIfInvalid() {
+        if (!isEnabled()) {
+            return false;
+        }
+        // Refresh mCardId if it's invalid.
+        if (mCardId == TelephonyManager.INVALID_CARD_ID) {
+            TelephonyManager tm = (TelephonyManager)
+                    mContext.getSystemService(Context.TELEPHONY_SERVICE);
+            mCardId = tm.getCardIdForDefaultEuicc();
+        }
+        return true;
+    }
+
     private static void sendUnavailableError(PendingIntent callbackIntent) {
         try {
             callbackIntent.send(EMBEDDED_SUBSCRIPTION_RESULT_ERROR);
diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java
new file mode 100644
index 0000000..ac4d17a
--- /dev/null
+++ b/telephony/java/android/telephony/ims/ImsException.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.text.TextUtils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class defines an IMS-related exception that has been thrown while interacting with a
+ * device or carrier provided ImsService implementation.
+ * @hide
+ */
+@SystemApi
+public class ImsException extends Exception {
+
+    /**
+     * The operation has failed due to an unknown or unspecified error.
+     */
+    public static final int CODE_ERROR_UNSPECIFIED = 0;
+    /**
+     * The operation has failed because there is no {@link ImsService} available to service it. This
+     * may be due to an {@link ImsService} crash or other illegal state.
+     * <p>
+     * This is a temporary error and the operation may be retried until the connection to the
+     * {@link ImsService} is restored.
+     */
+    public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1;
+
+    /**
+     * This device or carrier configuration does not support IMS for this subscription.
+     * <p>
+     * This is a permanent configuration error and there should be no retry.
+     */
+    public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2;
+
+    /**@hide*/
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "CODE_ERROR_", value = {
+            CODE_ERROR_UNSPECIFIED,
+            CODE_ERROR_SERVICE_UNAVAILABLE,
+            CODE_ERROR_UNSUPPORTED_OPERATION
+    })
+    public @interface ImsErrorCode {}
+
+    private int mCode = CODE_ERROR_UNSPECIFIED;
+
+    /**
+     * A new {@link ImsException} with an unspecified {@link ImsErrorCode} code.
+     * @param message an optional message to detail the error condition more specifically.
+     */
+    public ImsException(@Nullable String message) {
+        super(getMessage(message, CODE_ERROR_UNSPECIFIED));
+    }
+
+    /**
+     * A new {@link ImsException} that includes an {@link ImsErrorCode} error code.
+     * @param message an optional message to detail the error condition more specifically.
+     */
+    public ImsException(@Nullable String message, @ImsErrorCode int code) {
+        super(getMessage(message, code));
+        mCode = code;
+    }
+
+    /**
+     * A new {@link ImsException} that includes an {@link ImsErrorCode} error code and a
+     * {@link Throwable} that contains the original error that was thrown to lead to this Exception.
+     * @param message an optional message to detail the error condition more specifically.
+     * @param cause the {@link Throwable} that caused this {@link ImsException} to be created.
+     */
+    public ImsException(@Nullable String message, @ImsErrorCode  int code, Throwable cause) {
+        super(getMessage(message, code), cause);
+        mCode = code;
+    }
+
+    /**
+     * @return the IMS Error code that is associated with this {@link ImsException}.
+     */
+    public @ImsErrorCode int getCode() {
+        return mCode;
+    }
+
+    private static String getMessage(String message, int code) {
+        StringBuilder builder;
+        if (!TextUtils.isEmpty(message)) {
+            builder = new StringBuilder(message);
+            builder.append(" (code: ");
+            builder.append(code);
+            builder.append(")");
+            return builder.toString();
+        } else {
+            return "code: " + code;
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 5b2e635..eb99d5d 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -54,7 +54,7 @@
  * registration and MmTel capability status callbacks, as well as query/modify user settings for the
  * associated subscription.
  *
- * @see #createForSubscriptionId(Context, int)
+ * @see #createForSubscriptionId(int)
  * @hide
  */
 @SystemApi
@@ -315,15 +315,12 @@
     /**
      * Create an instance of ImsManager for the subscription id specified.
      *
-     * @param context The context to create this ImsMmTelManager instance within.
      * @param subId The ID of the subscription that this ImsMmTelManager will use.
      * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
-     * @throws IllegalArgumentException if the subscription is invalid or
-     *         the subscription ID is not an active subscription.
+     * @throws IllegalArgumentException if the subscription is invalid.
      */
-    public static ImsMmTelManager createForSubscriptionId(Context context, int subId) {
-        if (!SubscriptionManager.isValidSubscriptionId(subId)
-                || !getSubscriptionManager(context).isActiveSubscriptionId(subId)) {
+    public static ImsMmTelManager createForSubscriptionId(int subId) {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             throw new IllegalArgumentException("Invalid subscription ID");
         }
 
@@ -331,7 +328,7 @@
     }
 
     /**
-     * Only visible for testing, use {@link #createForSubscriptionId(Context, int)} instead.
+     * Only visible for testing, use {@link #createForSubscriptionId(int)} instead.
      * @hide
      */
     @VisibleForTesting
@@ -341,7 +338,7 @@
 
     /**
      * Registers a {@link RegistrationCallback} with the system, which will provide registration
-     * updates for the subscription specified in {@link #createForSubscriptionId(Context, int)}. Use
+     * updates for the subscription specified in {@link #createForSubscriptionId(int)}. Use
      * {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed
      * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
      *
@@ -354,13 +351,14 @@
      * @throws IllegalArgumentException if the subscription associated with this callback is not
      * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or
      * {@link CapabilityCallback} callback.
-     * @throws IllegalStateException if the subscription associated with this callback is valid, but
+     * @throws ImsException if the subscription associated with this callback is valid, but
      * the {@link ImsService} associated with the subscription is not available. This can happen if
-     * the service crashed, for example.
+     * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
+     * reason.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void registerImsRegistrationCallback(@CallbackExecutor Executor executor,
-            @NonNull RegistrationCallback c) {
+            @NonNull RegistrationCallback c) throws ImsException {
         if (c == null) {
             throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
         }
@@ -372,6 +370,8 @@
             getITelephony().registerImsRegistrationCallback(mSubId, c.getBinder());
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
+        } catch (IllegalStateException e) {
+            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
 
@@ -403,7 +403,7 @@
     /**
      * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service
      * availability updates for the subscription specified in
-     * {@link #createForSubscriptionId(Context, int)}. The method {@link #isAvailable(int, int)}
+     * {@link #createForSubscriptionId(int)}. The method {@link #isAvailable(int, int)}
      * can also be used to query this information at any time.
      *
      * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
@@ -419,13 +419,14 @@
      * @throws IllegalArgumentException if the subscription associated with this callback is not
      * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or
      * {@link CapabilityCallback} callback.
-     * @throws IllegalStateException if the subscription associated with this callback is valid, but
+     * @throws ImsException if the subscription associated with this callback is valid, but
      * the {@link ImsService} associated with the subscription is not available. This can happen if
-     * the service crashed, for example.
+     * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
+     * reason.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void registerMmTelCapabilityCallback(@NonNull @CallbackExecutor Executor executor,
-            @NonNull CapabilityCallback c) {
+            @NonNull CapabilityCallback c) throws ImsException {
         if (c == null) {
             throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
         }
@@ -437,6 +438,8 @@
             getITelephony().registerMmTelCapabilityCallback(mSubId, c.getBinder());
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
+        }  catch (IllegalStateException e) {
+            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
 
@@ -796,14 +799,6 @@
         }
     }
 
-    private static SubscriptionManager getSubscriptionManager(Context context) {
-        SubscriptionManager manager = context.getSystemService(SubscriptionManager.class);
-        if (manager == null) {
-            throw new RuntimeException("Could not find SubscriptionManager.");
-        }
-        return manager;
-    }
-
     private static ITelephony getITelephony() {
         ITelephony binder = ITelephony.Stub.asInterface(
                 ServiceManager.getService(Context.TELEPHONY_SERVICE));
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index 4d95e55..d8d2d9e 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -465,7 +465,7 @@
     public static final int CODE_USER_REJECTED_SESSION_MODIFICATION = 511;
 
     /**
-    * Upgrade Downgrade request cacncelled by the user who initiated it
+    * Upgrade Downgrade request cancelled by the user who initiated it
     */
     public static final int CODE_USER_CANCELLED_SESSION_MODIFICATION = 512;
 
@@ -887,6 +887,185 @@
     public static final int CODE_OEM_CAUSE_15 = 0xf00f;
 
     /**
+     * @hide
+     */
+    @IntDef(value = {
+            CODE_UNSPECIFIED,
+            CODE_LOCAL_ILLEGAL_ARGUMENT,
+            CODE_LOCAL_ILLEGAL_STATE,
+            CODE_LOCAL_INTERNAL_ERROR,
+            CODE_LOCAL_IMS_SERVICE_DOWN,
+            CODE_LOCAL_NO_PENDING_CALL,
+            CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE,
+            CODE_LOCAL_POWER_OFF,
+            CODE_LOCAL_LOW_BATTERY,
+            CODE_LOCAL_NETWORK_NO_SERVICE,
+            CODE_LOCAL_NETWORK_NO_LTE_COVERAGE,
+            CODE_LOCAL_NETWORK_ROAMING,
+            CODE_LOCAL_NETWORK_IP_CHANGED,
+            CODE_LOCAL_SERVICE_UNAVAILABLE,
+            CODE_LOCAL_NOT_REGISTERED,
+            CODE_LOCAL_CALL_EXCEEDED,
+            CODE_LOCAL_CALL_BUSY,
+            CODE_LOCAL_CALL_DECLINE,
+            CODE_LOCAL_CALL_VCC_ON_PROGRESSING,
+            CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED,
+            CODE_LOCAL_CALL_CS_RETRY_REQUIRED,
+            CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED,
+            CODE_LOCAL_CALL_TERMINATED,
+            CODE_LOCAL_HO_NOT_FEASIBLE,
+            CODE_TIMEOUT_1XX_WAITING,
+            CODE_TIMEOUT_NO_ANSWER,
+            CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE,
+            CODE_CALL_BARRED,
+            CODE_FDN_BLOCKED,
+            CODE_IMEI_NOT_ACCEPTED,
+            CODE_DIAL_MODIFIED_TO_USSD,
+            CODE_DIAL_MODIFIED_TO_SS,
+            CODE_DIAL_MODIFIED_TO_DIAL,
+            CODE_DIAL_MODIFIED_TO_DIAL_VIDEO,
+            CODE_DIAL_VIDEO_MODIFIED_TO_DIAL,
+            CODE_DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO,
+            CODE_DIAL_VIDEO_MODIFIED_TO_SS,
+            CODE_DIAL_VIDEO_MODIFIED_TO_USSD,
+            CODE_SIP_REDIRECTED,
+            CODE_SIP_BAD_REQUEST,
+            CODE_SIP_FORBIDDEN,
+            CODE_SIP_NOT_FOUND,
+            CODE_SIP_NOT_SUPPORTED,
+            CODE_SIP_REQUEST_TIMEOUT,
+            CODE_SIP_TEMPRARILY_UNAVAILABLE,
+            CODE_SIP_BAD_ADDRESS,
+            CODE_SIP_BUSY,
+            CODE_SIP_REQUEST_CANCELLED,
+            CODE_SIP_NOT_ACCEPTABLE,
+            CODE_SIP_NOT_REACHABLE,
+            CODE_SIP_CLIENT_ERROR,
+            CODE_SIP_TRANSACTION_DOES_NOT_EXIST,
+            CODE_SIP_SERVER_INTERNAL_ERROR,
+            CODE_SIP_SERVICE_UNAVAILABLE,
+            CODE_SIP_SERVER_TIMEOUT,
+            CODE_SIP_SERVER_ERROR,
+            CODE_SIP_USER_REJECTED,
+            CODE_SIP_GLOBAL_ERROR,
+            CODE_EMERGENCY_TEMP_FAILURE,
+            CODE_EMERGENCY_PERM_FAILURE,
+            CODE_SIP_USER_MARKED_UNWANTED,
+            CODE_SIP_METHOD_NOT_ALLOWED,
+            CODE_SIP_PROXY_AUTHENTICATION_REQUIRED,
+            CODE_SIP_REQUEST_ENTITY_TOO_LARGE,
+            CODE_SIP_REQUEST_URI_TOO_LARGE,
+            CODE_SIP_EXTENSION_REQUIRED,
+            CODE_SIP_INTERVAL_TOO_BRIEF,
+            CODE_SIP_CALL_OR_TRANS_DOES_NOT_EXIST,
+            CODE_SIP_LOOP_DETECTED,
+            CODE_SIP_TOO_MANY_HOPS,
+            CODE_SIP_AMBIGUOUS,
+            CODE_SIP_REQUEST_PENDING,
+            CODE_SIP_UNDECIPHERABLE,
+            CODE_MEDIA_INIT_FAILED,
+            CODE_MEDIA_NO_DATA,
+            CODE_MEDIA_NOT_ACCEPTABLE,
+            CODE_MEDIA_UNSPECIFIED,
+            CODE_USER_TERMINATED,
+            CODE_USER_NOANSWER,
+            CODE_USER_IGNORE,
+            CODE_USER_DECLINE,
+            CODE_LOW_BATTERY,
+            CODE_BLACKLISTED_CALL_ID,
+            CODE_USER_TERMINATED_BY_REMOTE,
+            CODE_USER_REJECTED_SESSION_MODIFICATION,
+            CODE_USER_CANCELLED_SESSION_MODIFICATION,
+            CODE_SESSION_MODIFICATION_FAILED,
+            CODE_UT_NOT_SUPPORTED,
+            CODE_UT_SERVICE_UNAVAILABLE,
+            CODE_UT_OPERATION_NOT_ALLOWED,
+            CODE_UT_NETWORK_ERROR,
+            CODE_UT_CB_PASSWORD_MISMATCH,
+            CODE_UT_SS_MODIFIED_TO_DIAL,
+            CODE_UT_SS_MODIFIED_TO_USSD,
+            CODE_UT_SS_MODIFIED_TO_SS,
+            CODE_UT_SS_MODIFIED_TO_DIAL_VIDEO,
+            CODE_ECBM_NOT_SUPPORTED,
+            CODE_MULTIENDPOINT_NOT_SUPPORTED,
+            CODE_REGISTRATION_ERROR,
+            CODE_ANSWERED_ELSEWHERE,
+            CODE_CALL_PULL_OUT_OF_SYNC,
+            CODE_CALL_END_CAUSE_CALL_PULL,
+            CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE,
+            CODE_REJECTED_ELSEWHERE,
+            CODE_SUPP_SVC_FAILED,
+            CODE_SUPP_SVC_CANCELLED,
+            CODE_SUPP_SVC_REINVITE_COLLISION,
+            CODE_IWLAN_DPD_FAILURE,
+            CODE_EPDG_TUNNEL_ESTABLISH_FAILURE,
+            CODE_EPDG_TUNNEL_REKEY_FAILURE,
+            CODE_EPDG_TUNNEL_LOST_CONNECTION,
+            CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED,
+            CODE_REMOTE_CALL_DECLINE,
+            CODE_DATA_LIMIT_REACHED,
+            CODE_DATA_DISABLED,
+            CODE_WIFI_LOST,
+            CODE_IKEV2_AUTH_FAILURE,
+            CODE_RADIO_OFF,
+            CODE_NO_VALID_SIM,
+            CODE_RADIO_INTERNAL_ERROR,
+            CODE_NETWORK_RESP_TIMEOUT,
+            CODE_NETWORK_REJECT,
+            CODE_RADIO_ACCESS_FAILURE,
+            CODE_RADIO_LINK_FAILURE,
+            CODE_RADIO_LINK_LOST,
+            CODE_RADIO_UPLINK_FAILURE,
+            CODE_RADIO_SETUP_FAILURE,
+            CODE_RADIO_RELEASE_NORMAL,
+            CODE_RADIO_RELEASE_ABNORMAL,
+            CODE_ACCESS_CLASS_BLOCKED,
+            CODE_NETWORK_DETACH,
+            CODE_SIP_ALTERNATE_EMERGENCY_CALL,
+            CODE_UNOBTAINABLE_NUMBER,
+            CODE_NO_CSFB_IN_CS_ROAM,
+            CODE_REJECT_UNKNOWN,
+            CODE_REJECT_ONGOING_CALL_WAITING_DISABLED,
+            CODE_REJECT_CALL_ON_OTHER_SUB,
+            CODE_REJECT_1X_COLLISION,
+            CODE_REJECT_SERVICE_NOT_REGISTERED,
+            CODE_REJECT_CALL_TYPE_NOT_ALLOWED,
+            CODE_REJECT_ONGOING_E911_CALL,
+            CODE_REJECT_ONGOING_CALL_SETUP,
+            CODE_REJECT_MAX_CALL_LIMIT_REACHED,
+            CODE_REJECT_UNSUPPORTED_SIP_HEADERS,
+            CODE_REJECT_UNSUPPORTED_SDP_HEADERS,
+            CODE_REJECT_ONGOING_CALL_TRANSFER,
+            CODE_REJECT_INTERNAL_ERROR,
+            CODE_REJECT_QOS_FAILURE,
+            CODE_REJECT_ONGOING_HANDOVER,
+            CODE_REJECT_VT_TTY_NOT_ALLOWED,
+            CODE_REJECT_ONGOING_CALL_UPGRADE,
+            CODE_REJECT_CONFERENCE_TTY_NOT_ALLOWED,
+            CODE_REJECT_ONGOING_CONFERENCE_CALL,
+            CODE_REJECT_VT_AVPF_NOT_ALLOWED,
+            CODE_REJECT_ONGOING_ENCRYPTED_CALL,
+            CODE_REJECT_ONGOING_CS_CALL,
+            CODE_OEM_CAUSE_1,
+            CODE_OEM_CAUSE_2,
+            CODE_OEM_CAUSE_3,
+            CODE_OEM_CAUSE_4,
+            CODE_OEM_CAUSE_5,
+            CODE_OEM_CAUSE_6,
+            CODE_OEM_CAUSE_7,
+            CODE_OEM_CAUSE_8,
+            CODE_OEM_CAUSE_9,
+            CODE_OEM_CAUSE_10,
+            CODE_OEM_CAUSE_11,
+            CODE_OEM_CAUSE_12,
+            CODE_OEM_CAUSE_13,
+            CODE_OEM_CAUSE_14,
+            CODE_OEM_CAUSE_15
+    }, prefix = "CODE_")
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ImsCode {}
+
+    /**
      * Network string error messages.
      * mExtraMessage may have these values.
      */
@@ -964,7 +1143,7 @@
     /**
      * @return an integer representing more information about the completion of an operation.
      */
-    public int getCode() {
+    public @ImsCode int getCode() {
         return mCode;
     }
 
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 086a765..204891b 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -172,15 +172,13 @@
 
     /**
      * Create a new {@link ProvisioningManager} for the subscription specified.
-     * @param context The context that this manager will use.
+     *
      * @param subId The ID of the subscription that this ProvisioningManager will use.
      * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
-     * @throws IllegalArgumentException if the subscription is invalid or
-     *         the subscription ID is not an active subscription.
+     * @throws IllegalArgumentException if the subscription is invalid.
      */
-    public static ProvisioningManager createForSubscriptionId(Context context, int subId) {
-        if (!SubscriptionManager.isValidSubscriptionId(subId)
-                || !getSubscriptionManager(context).isActiveSubscriptionId(subId)) {
+    public static ProvisioningManager createForSubscriptionId(int subId) {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             throw new IllegalArgumentException("Invalid subscription ID");
         }
 
@@ -202,18 +200,21 @@
      * @see SubscriptionManager.OnSubscriptionsChangedListener
      * @throws IllegalArgumentException if the subscription associated with this callback is not
      * active (SIM is not inserted, ESIM inactive) or the subscription is invalid.
-     * @throws IllegalStateException if the subscription associated with this callback is valid, but
+     * @throws ImsException if the subscription associated with this callback is valid, but
      * the {@link ImsService} associated with the subscription is not available. This can happen if
-     * the service crashed, for example.
+     * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
+     * reason.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void registerProvisioningChangedCallback(@CallbackExecutor Executor executor,
-            @NonNull Callback callback) {
+            @NonNull Callback callback) throws ImsException {
         callback.setExecutor(executor);
         try {
             getITelephony().registerImsProvisioningChangedCallback(mSubId, callback.getBinder());
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
+        }  catch (IllegalStateException e) {
+            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
 
@@ -369,14 +370,6 @@
         }
     }
 
-    private static SubscriptionManager getSubscriptionManager(Context context) {
-        SubscriptionManager manager = context.getSystemService(SubscriptionManager.class);
-        if (manager == null) {
-            throw new RuntimeException("Could not find SubscriptionManager.");
-        }
-        return manager;
-    }
-
     private static ITelephony getITelephony() {
         ITelephony binder = ITelephony.Stub.asInterface(
                 ServiceManager.getService(Context.TELEPHONY_SERVICE));
diff --git a/telephony/java/com/android/ims/ImsException.java b/telephony/java/com/android/ims/ImsException.java
index f35e886..fea763e 100644
--- a/telephony/java/com/android/ims/ImsException.java
+++ b/telephony/java/com/android/ims/ImsException.java
@@ -21,8 +21,10 @@
 /**
  * This class defines a general IMS-related exception.
  *
+ * @deprecated Use {@link android.telephony.ims.ImsException} instead.
  * @hide
  */
+@Deprecated
 public class ImsException extends Exception {
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/EncodeException.java b/telephony/java/com/android/internal/telephony/EncodeException.java
index 4e3fac1..cdc853e 100644
--- a/telephony/java/com/android/internal/telephony/EncodeException.java
+++ b/telephony/java/com/android/internal/telephony/EncodeException.java
@@ -22,6 +22,12 @@
  * {@hide}
  */
 public class EncodeException extends Exception {
+
+    private int mError = ERROR_UNENCODABLE;
+
+    public static final int ERROR_UNENCODABLE = 0;
+    public static final int ERROR_EXCEED_SIZE = 1;
+
     public EncodeException() {
         super();
     }
@@ -31,9 +37,18 @@
         super(s);
     }
 
+    public EncodeException(String s, int error) {
+        super(s);
+        mError = error;
+    }
+
     @UnsupportedAppUsage
     public EncodeException(char c) {
         super("Unencodable char: '" + c + "'");
     }
+
+    public int getError() {
+        return mError;
+    }
 }
 
diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
index 84c0e64..a774cdc 100644
--- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java
+++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
@@ -388,7 +388,7 @@
      *     GSM extension table
      * @return the encoded message
      *
-     * @throws EncodeException if String is too large to encode
+     * @throws EncodeException if String is too large to encode or any characters are unencodable
      */
     @UnsupportedAppUsage
     public static byte[] stringToGsm7BitPacked(String data, int startingSeptetOffset,
@@ -402,7 +402,8 @@
         }
         septetCount += startingSeptetOffset;
         if (septetCount > 255) {
-            throw new EncodeException("Payload cannot exceed 255 septets");
+            throw new EncodeException(
+                    "Payload cannot exceed 255 septets", EncodeException.ERROR_EXCEED_SIZE);
         }
         int byteCount = ((septetCount * 7) + 7) / 8;
         byte[] ret = new byte[byteCount + 1];  // Include space for one byte length prefix.
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 3dbebe8..322ce45 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -27,6 +27,7 @@
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.emergency.EmergencyNumber;
+import android.telephony.ims.ImsReasonInfo;
 
 oneway interface IPhoneStateListener {
     void onServiceStateChanged(in ServiceState serviceState);
@@ -58,5 +59,6 @@
     void onCallAttributesChanged(in CallAttributes callAttributes);
     void onEmergencyNumberListChanged(in Map emergencyNumberList);
     void onCallDisconnectCauseChanged(in int disconnectCause, in int preciseDisconnectCause);
+    void onImsCallDisconnectCauseChanged(in ImsReasonInfo imsReasonInfo);
 }
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 77a63bd..c7061df 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1817,4 +1817,31 @@
      * Enable or disable a logical modem stack associated with the slotIndex.
      */
     boolean enableModemForSlot(int slotIndex, boolean enable);
+
+    /**
+     * Indicate if the enablement of multi SIM functionality is restricted.
+     * @hide
+     */
+    void setMultisimCarrierRestriction(boolean isMultisimCarrierRestricted);
+
+    /**
+     * Returns if the usage of multiple SIM cards at the same time is restricted.
+     * @hide
+     */
+    boolean isMultisimCarrierRestricted();
+    
+    /**
+     * Switch configs to enable multi-sim or switch back to single-sim
+     * @hide
+     */
+    void switchMultiSimConfig(int numOfSims);
+    /**
+     * Get how many modems have been activated on the phone
+     * @hide
+     */
+    int getNumOfActiveSims();
+    /**
+     * Get if reboot is required upon altering modems configurations
+     */
+    boolean isRebootRequiredForModemConfigChange();
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 2be1f41..e9eba32 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -22,6 +22,7 @@
 import android.os.Bundle;
 import android.telephony.CallQuality;
 import android.telephony.CellInfo;
+import android.telephony.ims.ImsReasonInfo;
 import android.telephony.PhoneCapability;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.ServiceState;
@@ -84,4 +85,5 @@
     void notifyRadioPowerStateChanged(in int state);
     void notifyEmergencyNumberList();
     void notifyCallQualityChanged(in CallQuality callQuality, int phoneId);
+    void notifyImsDisconnectCause(int subId, in ImsReasonInfo imsReasonInfo);
 }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index f901c0e..77b7979 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -128,32 +128,108 @@
     int OEM_ERROR_25 = 525;
 
     /* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */
-    int NETWORK_MODE_WCDMA_PREF     = 0; /* GSM/WCDMA (WCDMA preferred) */
-    int NETWORK_MODE_GSM_ONLY       = 1; /* GSM only */
-    int NETWORK_MODE_WCDMA_ONLY     = 2; /* WCDMA only */
-    int NETWORK_MODE_GSM_UMTS       = 3; /* GSM/WCDMA (auto mode, according to PRL)
-                                            AVAILABLE Application Settings menu*/
-    int NETWORK_MODE_CDMA           = 4; /* CDMA and EvDo (auto mode, according to PRL)
-                                            AVAILABLE Application Settings menu*/
-    int NETWORK_MODE_CDMA_NO_EVDO   = 5; /* CDMA only */
-    int NETWORK_MODE_EVDO_NO_CDMA   = 6; /* EvDo only */
-    int NETWORK_MODE_GLOBAL         = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)
-                                            AVAILABLE Application Settings menu*/
-    int NETWORK_MODE_LTE_CDMA_EVDO  = 8; /* LTE, CDMA and EvDo */
-    int NETWORK_MODE_LTE_GSM_WCDMA  = 9; /* LTE, GSM/WCDMA */
-    int NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA = 10; /* LTE, CDMA, EvDo, GSM/WCDMA */
-    int NETWORK_MODE_LTE_ONLY       = 11; /* LTE Only mode. */
-    int NETWORK_MODE_LTE_WCDMA      = 12; /* LTE/WCDMA */
-    int NETWORK_MODE_TDSCDMA_ONLY            = 13; /* TD-SCDMA only */
-    int NETWORK_MODE_TDSCDMA_WCDMA           = 14; /* TD-SCDMA and WCDMA */
-    int NETWORK_MODE_LTE_TDSCDMA             = 15; /* TD-SCDMA and LTE */
-    int NETWORK_MODE_TDSCDMA_GSM             = 16; /* TD-SCDMA and GSM */
-    int NETWORK_MODE_LTE_TDSCDMA_GSM         = 17; /* TD-SCDMA,GSM and LTE */
-    int NETWORK_MODE_TDSCDMA_GSM_WCDMA       = 18; /* TD-SCDMA, GSM/WCDMA */
-    int NETWORK_MODE_LTE_TDSCDMA_WCDMA       = 19; /* TD-SCDMA, WCDMA and LTE */
-    int NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA   = 20; /* TD-SCDMA, GSM/WCDMA and LTE */
-    int NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA  = 21; /*TD-SCDMA,EvDo,CDMA,GSM/WCDMA*/
-    int NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 22; /* TD-SCDMA/LTE/GSM/WCDMA, CDMA, and EvDo */
+    /** GSM, WCDMA (WCDMA preferred) */
+    int NETWORK_MODE_WCDMA_PREF = 0;
+
+    /** GSM only */
+    int NETWORK_MODE_GSM_ONLY = 1;
+
+    /** WCDMA only */
+    int NETWORK_MODE_WCDMA_ONLY = 2;
+
+    /** GSM, WCDMA (auto mode, according to PRL) */
+    int NETWORK_MODE_GSM_UMTS = 3;
+
+    /** CDMA and EvDo (auto mode, according to PRL) */
+    int NETWORK_MODE_CDMA = 4;
+
+    /** CDMA only */
+    int NETWORK_MODE_CDMA_NO_EVDO = 5;
+
+    /** EvDo only */
+    int NETWORK_MODE_EVDO_NO_CDMA = 6;
+
+    /** GSM, WCDMA, CDMA, and EvDo (auto mode, according to PRL) */
+    int NETWORK_MODE_GLOBAL = 7;
+
+    /** LTE, CDMA and EvDo */
+    int NETWORK_MODE_LTE_CDMA_EVDO = 8;
+
+    /** LTE, GSM and WCDMA */
+    int NETWORK_MODE_LTE_GSM_WCDMA = 9;
+
+    /** LTE, CDMA, EvDo, GSM, and WCDMA */
+    int NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA = 10;
+
+    /** LTE only mode. */
+    int NETWORK_MODE_LTE_ONLY = 11;
+
+    /** LTE and WCDMA */
+    int NETWORK_MODE_LTE_WCDMA = 12;
+
+    /** TD-SCDMA only */
+    int NETWORK_MODE_TDSCDMA_ONLY = 13;
+
+    /** TD-SCDMA and WCDMA */
+    int NETWORK_MODE_TDSCDMA_WCDMA = 14;
+
+    /** LTE and TD-SCDMA*/
+    int NETWORK_MODE_LTE_TDSCDMA = 15;
+
+    /** TD-SCDMA and GSM */
+    int NETWORK_MODE_TDSCDMA_GSM = 16;
+
+    /** TD-SCDMA, GSM and LTE */
+    int NETWORK_MODE_LTE_TDSCDMA_GSM = 17;
+
+    /** TD-SCDMA, GSM and WCDMA */
+    int NETWORK_MODE_TDSCDMA_GSM_WCDMA = 18;
+
+    /** LTE, TD-SCDMA and WCDMA */
+    int NETWORK_MODE_LTE_TDSCDMA_WCDMA = 19;
+
+    /** LTE, TD-SCDMA, GSM, and WCDMA */
+    int NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA = 20;
+
+    /** TD-SCDMA, CDMA, EVDO, GSM and WCDMA */
+    int NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 21;
+
+    /** LTE, TDCSDMA, CDMA, EVDO, GSM and WCDMA */
+    int NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 22;
+
+    /** NR 5G only mode */
+    int NETWORK_MODE_NR_ONLY = 23;
+
+    /** NR 5G, LTE */
+    int NETWORK_MODE_NR_LTE = 24;
+
+    /** NR 5G, LTE, CDMA and EvDo */
+    int NETWORK_MODE_NR_LTE_CDMA_EVDO = 25;
+
+    /** NR 5G, LTE, GSM and WCDMA */
+    int NETWORK_MODE_NR_LTE_GSM_WCDMA = 26;
+
+    /** NR 5G, LTE, CDMA, EvDo, GSM and WCDMA */
+    int NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA = 27;
+
+    /** NR 5G, LTE and WCDMA */
+    int NETWORK_MODE_NR_LTE_WCDMA = 28;
+
+    /** NR 5G, LTE and TDSCDMA */
+    int NETWORK_MODE_NR_LTE_TDSCDMA = 29;
+
+    /** NR 5G, LTE, TD-SCDMA and GSM */
+    int NETWORK_MODE_NR_LTE_TDSCDMA_GSM = 30;
+
+    /** NR 5G, LTE, TD-SCDMA, WCDMA */
+    int NETWORK_MODE_NR_LTE_TDSCDMA_WCDMA = 31;
+
+    /** NR 5G, LTE, TD-SCDMA, GSM and WCDMA */
+    int NETWORK_MODE_NR_LTE_TDSCDMA_GSM_WCDMA = 32;
+
+    /** NR 5G, LTE, TD-SCDMA, CDMA, EVDO, GSM and WCDMA */
+    int NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 33;
+
     int PREFERRED_NETWORK_MODE = Integer.parseInt(TelephonyManager.getTelephonyProperty(0,
             "ro.telephony.default_network", Integer.toString(NETWORK_MODE_WCDMA_PREF)));
 
@@ -404,6 +480,7 @@
     int RIL_REQUEST_SET_PREFERRED_DATA_MODEM = 204;
     int RIL_REQUEST_EMERGENCY_DIAL = 205;
     int RIL_REQUEST_GET_PHONE_CAPABILITY = 206;
+    int RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG = 207;
 
     /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 6567ea7..603c4c2 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -194,6 +194,13 @@
      */
     static final String PROPERTY_MULTI_SIM_CONFIG = "persist.radio.multisim.config";
 
+     /**
+     * Property to indicate if reboot is required when changing modems configurations
+     * Type:  String(true, false) default is false; most devices don't need reboot
+     */
+    String PROPERTY_REBOOT_REQUIRED_ON_MODEM_CHANGE =
+             "persist.radio.reboot_on_modem_change";
+
     /**
      * Property to store default subscription.
      */
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index 14a36c8..2016915 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -31,7 +31,7 @@
         String callingPackage, in PendingIntent callbackIntent);
     oneway void getDefaultDownloadableSubscriptionList(int cardId,
         String callingPackage, in PendingIntent callbackIntent);
-    String getEid(int cardId);
+    String getEid(int cardId, String callingPackage);
     int getOtaStatus(int cardId);
     oneway void downloadSubscription(int cardId, in DownloadableSubscription subscription,
         boolean switchAfterDownload, String callingPackage, in Bundle resolvedBundle,
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index 4f5bfa9..015efa6 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -384,16 +384,22 @@
                 }
             }
         } catch (EncodeException ex) {
-            // Encoding to the 7-bit alphabet failed. Let's see if we can
-            // send it as a UCS-2 encoded message
-            try {
-                userData = encodeUCS2(message, header);
-                encoding = ENCODING_16BIT;
-            } catch(UnsupportedEncodingException uex) {
-                Rlog.e(LOG_TAG,
-                        "Implausible UnsupportedEncodingException ",
-                        uex);
+            if (ex.getError() == EncodeException.ERROR_EXCEED_SIZE) {
+                Rlog.e(LOG_TAG, "Exceed size limitation EncodeException", ex);
                 return null;
+            } else {
+                // Encoding to the 7-bit alphabet failed. Let's see if we can
+                // send it as a UCS-2 encoded message
+                try {
+                    userData = encodeUCS2(message, header);
+                    encoding = ENCODING_16BIT;
+                } catch (EncodeException ex1) {
+                    Rlog.e(LOG_TAG, "Exceed size limitation EncodeException", ex1);
+                    return null;
+                } catch (UnsupportedEncodingException uex) {
+                    Rlog.e(LOG_TAG, "Implausible UnsupportedEncodingException ", uex);
+                    return null;
+                }
             }
         }
 
@@ -438,9 +444,10 @@
      *
      * @return encoded message as UCS2
      * @throws UnsupportedEncodingException
+     * @throws EncodeException if String is too large to encode
      */
     private static byte[] encodeUCS2(String message, byte[] header)
-        throws UnsupportedEncodingException {
+            throws UnsupportedEncodingException, EncodeException {
         byte[] userData, textPart;
         textPart = message.getBytes("utf-16be");
 
@@ -455,6 +462,10 @@
         else {
             userData = textPart;
         }
+        if (userData.length > 255) {
+            throw new EncodeException(
+                    "Payload cannot exceed 255 bytes", EncodeException.ERROR_EXCEED_SIZE);
+        }
         byte[] ret = new byte[userData.length+1];
         ret[0] = (byte) (userData.length & 0xff );
         System.arraycopy(userData, 0, ret, 1, userData.length);
diff --git a/tests/net/java/android/net/ip/InterfaceControllerTest.java b/tests/net/java/android/net/ip/InterfaceControllerTest.java
new file mode 100644
index 0000000..d27a4f9
--- /dev/null
+++ b/tests/net/java/android/net/ip/InterfaceControllerTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.ip;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.net.INetd;
+import android.net.InetAddresses;
+import android.net.InterfaceConfigurationParcel;
+import android.net.LinkAddress;
+import android.net.util.SharedLog;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class InterfaceControllerTest {
+    private static final String TEST_IFACE = "testif";
+    private static final String TEST_IPV4_ADDR = "192.168.123.28";
+    private static final int TEST_PREFIXLENGTH = 31;
+
+    @Mock private INetd mNetd;
+    @Mock private SharedLog mLog;
+    @Captor private ArgumentCaptor<InterfaceConfigurationParcel> mConfigCaptor;
+
+    private InterfaceController mController;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mController = new InterfaceController(TEST_IFACE, mNetd, mLog);
+
+        doNothing().when(mNetd).interfaceSetCfg(mConfigCaptor.capture());
+    }
+
+    @Test
+    public void testSetIPv4Address() throws Exception {
+        mController.setIPv4Address(
+                new LinkAddress(InetAddresses.parseNumericAddress(TEST_IPV4_ADDR),
+                        TEST_PREFIXLENGTH));
+        verify(mNetd, times(1)).interfaceSetCfg(any());
+        final InterfaceConfigurationParcel parcel = mConfigCaptor.getValue();
+        assertEquals(TEST_IFACE, parcel.ifName);
+        assertEquals(TEST_IPV4_ADDR, parcel.ipv4Addr);
+        assertEquals(TEST_PREFIXLENGTH, parcel.prefixLength);
+        assertEquals("", parcel.hwAddr);
+        assertArrayEquals(new String[0], parcel.flags);
+    }
+
+    @Test
+    public void testClearIPv4Address() throws Exception {
+        mController.clearIPv4Address();
+        verify(mNetd, times(1)).interfaceSetCfg(any());
+        final InterfaceConfigurationParcel parcel = mConfigCaptor.getValue();
+        assertEquals(TEST_IFACE, parcel.ifName);
+        assertEquals("0.0.0.0", parcel.ipv4Addr);
+        assertEquals(0, parcel.prefixLength);
+        assertEquals("", parcel.hwAddr);
+        assertArrayEquals(new String[0], parcel.flags);
+    }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 923c7dd..ebfb69e 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -57,6 +57,7 @@
 import static android.net.NetworkPolicyManager.RULE_NONE;
 import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
+import static android.net.shared.NetworkParcelableUtil.fromStableParcelable;
 
 import static com.android.internal.util.TestUtils.waitForIdleHandler;
 import static com.android.internal.util.TestUtils.waitForIdleLooper;
@@ -119,6 +120,7 @@
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkMisc;
+import android.net.NetworkParcelable;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
 import android.net.NetworkStack;
@@ -482,8 +484,8 @@
                 fail(e.getMessage());
             }
 
-            final ArgumentCaptor<Network> nmNetworkCaptor =
-                    ArgumentCaptor.forClass(Network.class);
+            final ArgumentCaptor<NetworkParcelable> nmNetworkCaptor =
+                    ArgumentCaptor.forClass(NetworkParcelable.class);
             final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
                     ArgumentCaptor.forClass(INetworkMonitorCallbacks.class);
             doNothing().when(mNetworkStack).makeNetworkMonitor(
@@ -523,7 +525,8 @@
                 }
             };
 
-            assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
+            assertEquals(
+                    mNetworkAgent.netId, fromStableParcelable(nmNetworkCaptor.getValue()).netId);
             mNmCallbacks = nmCbCaptor.getValue();
 
             try {
@@ -903,6 +906,7 @@
             mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
             mConnected = true;
             mConfig = new VpnConfig();
+            mConfig.isMetered = false;
         }
 
         @Override
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 5b17224..46de3d0 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -168,6 +168,8 @@
         ApplicationInfo applicationInfo = new ApplicationInfo();
         applicationInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT;
         when(mContext.getApplicationInfo()).thenReturn(applicationInfo);
+        when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+                .thenReturn(applicationInfo);
 
         doNothing().when(mNetService).registerObserver(any());
     }
@@ -544,23 +546,28 @@
         final Network wifi = new Network(2);
 
         final Map<Network, NetworkCapabilities> networks = new HashMap<>();
-        networks.put(mobile, new NetworkCapabilities()
-                .addTransportType(TRANSPORT_CELLULAR)
-                .addCapability(NET_CAPABILITY_INTERNET)
-                .addCapability(NET_CAPABILITY_NOT_METERED)
-                .addCapability(NET_CAPABILITY_NOT_CONGESTED)
-                .setLinkDownstreamBandwidthKbps(10));
-        networks.put(wifi, new NetworkCapabilities()
-                .addTransportType(TRANSPORT_WIFI)
-                .addCapability(NET_CAPABILITY_INTERNET)
-                .addCapability(NET_CAPABILITY_NOT_ROAMING)
-                .addCapability(NET_CAPABILITY_NOT_CONGESTED)
-                .setLinkUpstreamBandwidthKbps(20));
+        networks.put(
+                mobile,
+                new NetworkCapabilities()
+                        .addTransportType(TRANSPORT_CELLULAR)
+                        .addCapability(NET_CAPABILITY_INTERNET)
+                        .addCapability(NET_CAPABILITY_NOT_CONGESTED)
+                        .setLinkDownstreamBandwidthKbps(10));
+        networks.put(
+                wifi,
+                new NetworkCapabilities()
+                        .addTransportType(TRANSPORT_WIFI)
+                        .addCapability(NET_CAPABILITY_INTERNET)
+                        .addCapability(NET_CAPABILITY_NOT_METERED)
+                        .addCapability(NET_CAPABILITY_NOT_ROAMING)
+                        .addCapability(NET_CAPABILITY_NOT_CONGESTED)
+                        .setLinkUpstreamBandwidthKbps(20));
         setMockedNetworks(networks);
 
         final NetworkCapabilities caps = new NetworkCapabilities();
 
-        Vpn.updateCapabilities(mConnectivityManager, new Network[] { }, caps);
+        Vpn.updateCapabilities(
+                mConnectivityManager, new Network[] {}, caps, false /* isAlwaysMetered */);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
         assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
         assertFalse(caps.hasTransport(TRANSPORT_WIFI));
@@ -570,17 +577,33 @@
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        Vpn.updateCapabilities(mConnectivityManager, new Network[] { mobile }, caps);
+        Vpn.updateCapabilities(
+                mConnectivityManager,
+                new Network[] {mobile},
+                caps,
+                false /* isAlwaysMetered */);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
         assertTrue(caps.hasTransport(TRANSPORT_CELLULAR));
         assertFalse(caps.hasTransport(TRANSPORT_WIFI));
         assertEquals(10, caps.getLinkDownstreamBandwidthKbps());
         assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps());
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+        assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        Vpn.updateCapabilities(mConnectivityManager, new Network[] { wifi }, caps);
+        Vpn.updateCapabilities(
+                mConnectivityManager, new Network[] {wifi}, caps, false /* isAlwaysMetered */);
+        assertTrue(caps.hasTransport(TRANSPORT_VPN));
+        assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
+        assertTrue(caps.hasTransport(TRANSPORT_WIFI));
+        assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps());
+        assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
+
+        Vpn.updateCapabilities(
+                mConnectivityManager, new Network[] {wifi}, caps, true /* isAlwaysMetered */);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
         assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
         assertTrue(caps.hasTransport(TRANSPORT_WIFI));
@@ -590,7 +613,11 @@
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        Vpn.updateCapabilities(mConnectivityManager, new Network[] { mobile, wifi }, caps);
+        Vpn.updateCapabilities(
+                mConnectivityManager,
+                new Network[] {mobile, wifi},
+                caps,
+                false /* isAlwaysMetered */);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
         assertTrue(caps.hasTransport(TRANSPORT_CELLULAR));
         assertTrue(caps.hasTransport(TRANSPORT_WIFI));
diff --git a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
index 0f72229..ec286759 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
@@ -16,8 +16,16 @@
 
 package com.android.server.connectivity.tethering;
 
+import static android.net.ConnectivityManager.TETHERING_USB;
+import static android.net.ConnectivityManager.TETHERING_WIFI;
+import static android.net.ConnectivityManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
+import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
+import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
+
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
@@ -27,12 +35,22 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.net.util.SharedLog;
+import android.os.Bundle;
+import android.os.Message;
 import android.os.PersistableBundle;
+import android.os.ResultReceiver;
+import android.os.test.TestLooper;
+import android.provider.Settings;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.telephony.CarrierConfigManager;
+import android.test.mock.MockContentResolver;
 
 import com.android.internal.R;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+import com.android.internal.util.test.BroadcastInterceptingContext;
+import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.server.connectivity.MockableSystemProperties;
 
 import org.junit.After;
@@ -42,6 +60,10 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public final class EntitlementManagerTest {
@@ -51,7 +73,6 @@
 
     @Mock private CarrierConfigManager mCarrierConfigManager;
     @Mock private Context mContext;
-    @Mock private ContentResolver mContent;
     @Mock private MockableSystemProperties mSystemProperties;
     @Mock private Resources mResources;
     @Mock private SharedLog mLog;
@@ -59,15 +80,49 @@
     // Like so many Android system APIs, these cannot be mocked because it is marked final.
     // We have to use the real versions.
     private final PersistableBundle mCarrierConfig = new PersistableBundle();
+    private final TestLooper mLooper = new TestLooper();
+    private Context mMockContext;
+    private MockContentResolver mContentResolver;
 
-    private EntitlementManager mEnMgr;
+    private TestStateMachine mSM;
+    private WrappedEntitlementManager mEnMgr;
+
+    private class MockContext extends BroadcastInterceptingContext {
+        MockContext(Context base) {
+            super(base);
+        }
+
+        @Override
+        public Resources getResources() {
+            return mResources;
+        }
+
+        @Override
+        public ContentResolver getContentResolver() {
+            return mContentResolver;
+        }
+    }
+
+    public class WrappedEntitlementManager extends EntitlementManager {
+        public int fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKONWN;
+        public boolean everRunUiEntitlement = false;
+
+        public WrappedEntitlementManager(Context ctx, StateMachine target,
+                SharedLog log, MockableSystemProperties systemProperties) {
+            super(ctx, target, log, systemProperties);
+        }
+
+        @Override
+        protected void runUiTetherProvisioning(int type, ResultReceiver receiver) {
+            everRunUiEntitlement = true;
+            receiver.send(fakeEntitlementResult, null);
+        }
+    }
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
-        when(mContext.getResources()).thenReturn(mResources);
-        when(mContext.getContentResolver()).thenReturn(mContent);
         when(mResources.getStringArray(R.array.config_tether_dhcp_range))
             .thenReturn(new String[0]);
         when(mResources.getStringArray(R.array.config_tether_usb_regexs))
@@ -80,12 +135,21 @@
             .thenReturn(new int[0]);
         when(mLog.forSubComponent(anyString())).thenReturn(mLog);
 
-        mEnMgr = new EntitlementManager(mContext, mLog, mSystemProperties);
-        mEnMgr.updateConfiguration(new TetheringConfiguration(mContext, mLog));
+        mContentResolver = new MockContentResolver();
+        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+        mMockContext = new MockContext(mContext);
+        mSM = new TestStateMachine();
+        mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, mSystemProperties);
+        mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
     }
 
     @After
-    public void tearDown() throws Exception {}
+    public void tearDown() throws Exception {
+        if (mSM != null) {
+            mSM.quit();
+            mSM = null;
+        }
+    }
 
     private void setupForRequiredProvisioning() {
         // Produce some acceptable looking provision app setting if requested.
@@ -104,7 +168,7 @@
     @Test
     public void canRequireProvisioning() {
         setupForRequiredProvisioning();
-        mEnMgr.updateConfiguration(new TetheringConfiguration(mContext, mLog));
+        mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
         assertTrue(mEnMgr.isTetherProvisioningRequired());
     }
 
@@ -113,7 +177,7 @@
         setupForRequiredProvisioning();
         when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
             .thenReturn(null);
-        mEnMgr.updateConfiguration(new TetheringConfiguration(mContext, mLog));
+        mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
         // Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
         // Therefore provisioning still be required.
         assertTrue(mEnMgr.isTetherProvisioningRequired());
@@ -123,7 +187,7 @@
     public void toleratesCarrierConfigMissing() {
         setupForRequiredProvisioning();
         when(mCarrierConfigManager.getConfig()).thenReturn(null);
-        mEnMgr.updateConfiguration(new TetheringConfiguration(mContext, mLog));
+        mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
         // We still have a provisioning app configured, so still require provisioning.
         assertTrue(mEnMgr.isTetherProvisioningRequired());
     }
@@ -133,12 +197,143 @@
         setupForRequiredProvisioning();
         when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
             .thenReturn(null);
-        mEnMgr.updateConfiguration(new TetheringConfiguration(mContext, mLog));
+        mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
         assertFalse(mEnMgr.isTetherProvisioningRequired());
         when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
             .thenReturn(new String[] {"malformedApp"});
-        mEnMgr.updateConfiguration(new TetheringConfiguration(mContext, mLog));
+        mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
         assertFalse(mEnMgr.isTetherProvisioningRequired());
     }
 
+    @Test
+    public void testGetLastEntitlementCacheValue() throws Exception {
+        final CountDownLatch mCallbacklatch = new CountDownLatch(1);
+        // 1. Entitlement check is not required.
+        mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
+        mEnMgr.everRunUiEntitlement = false;
+        ResultReceiver receiver = new ResultReceiver(null) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                assertEquals(TETHER_ERROR_NO_ERROR, resultCode);
+                mCallbacklatch.countDown();
+            }
+        };
+        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
+        callbackTimeoutHelper(mCallbacklatch);
+        assertFalse(mEnMgr.everRunUiEntitlement);
+
+        setupForRequiredProvisioning();
+        mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog));
+        // 2. No cache value and don't need to run entitlement check.
+        mEnMgr.everRunUiEntitlement = false;
+        receiver = new ResultReceiver(null) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                assertEquals(TETHER_ERROR_ENTITLEMENT_UNKONWN, resultCode);
+                mCallbacklatch.countDown();
+            }
+        };
+        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, false);
+        callbackTimeoutHelper(mCallbacklatch);
+        assertFalse(mEnMgr.everRunUiEntitlement);
+        // 3. No cache value and ui entitlement check is needed.
+        mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
+        mEnMgr.everRunUiEntitlement = false;
+        receiver = new ResultReceiver(null) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                assertEquals(TETHER_ERROR_PROVISION_FAILED, resultCode);
+                mCallbacklatch.countDown();
+            }
+        };
+        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
+        mLooper.dispatchAll();
+        callbackTimeoutHelper(mCallbacklatch);
+        assertTrue(mEnMgr.everRunUiEntitlement);
+        // 4. Cache value is TETHER_ERROR_PROVISION_FAILED and don't need to run entitlement check.
+        mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
+        mEnMgr.everRunUiEntitlement = false;
+        receiver = new ResultReceiver(null) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                assertEquals(TETHER_ERROR_PROVISION_FAILED, resultCode);
+                mCallbacklatch.countDown();
+            }
+        };
+        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, false);
+        callbackTimeoutHelper(mCallbacklatch);
+        assertFalse(mEnMgr.everRunUiEntitlement);
+        // 5. Cache value is TETHER_ERROR_PROVISION_FAILED and ui entitlement check is needed.
+        mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
+        mEnMgr.everRunUiEntitlement = false;
+        receiver = new ResultReceiver(null) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                assertEquals(TETHER_ERROR_NO_ERROR, resultCode);
+                mCallbacklatch.countDown();
+            }
+        };
+        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
+        mLooper.dispatchAll();
+        callbackTimeoutHelper(mCallbacklatch);
+        assertTrue(mEnMgr.everRunUiEntitlement);
+        // 6. Cache value is TETHER_ERROR_NO_ERROR.
+        mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
+        mEnMgr.everRunUiEntitlement = false;
+        receiver = new ResultReceiver(null) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                assertEquals(TETHER_ERROR_NO_ERROR, resultCode);
+                mCallbacklatch.countDown();
+            }
+        };
+        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
+        callbackTimeoutHelper(mCallbacklatch);
+        assertFalse(mEnMgr.everRunUiEntitlement);
+        // 7. Test get value for other downstream type.
+        mEnMgr.everRunUiEntitlement = false;
+        receiver = new ResultReceiver(null) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                assertEquals(TETHER_ERROR_ENTITLEMENT_UNKONWN, resultCode);
+                mCallbacklatch.countDown();
+            }
+        };
+        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_USB, receiver, false);
+        callbackTimeoutHelper(mCallbacklatch);
+        assertFalse(mEnMgr.everRunUiEntitlement);
+    }
+
+    void callbackTimeoutHelper(final CountDownLatch latch) throws Exception {
+        if (!latch.await(1, TimeUnit.SECONDS)) {
+            fail("Timout, fail to recieve callback");
+        }
+    }
+    public class TestStateMachine extends StateMachine {
+        public final ArrayList<Message> messages = new ArrayList<>();
+        private final State mLoggingState =
+                new EntitlementManagerTest.TestStateMachine.LoggingState();
+
+        class LoggingState extends State {
+            @Override public void enter() {
+                messages.clear();
+            }
+
+            @Override public void exit() {
+                messages.clear();
+            }
+
+            @Override public boolean processMessage(Message msg) {
+                messages.add(msg);
+                return false;
+            }
+        }
+
+        public TestStateMachine() {
+            super("EntitlementManagerTest.TestStateMachine", mLooper.getLooper());
+            addState(mLoggingState);
+            setInitialState(mLoggingState);
+            super.start();
+        }
+    }
 }