Merge "new API for IMS call fail cause"
diff --git a/Android.bp b/Android.bp
index 225f86de..0407c41 100644
--- a/Android.bp
+++ b/Android.bp
@@ -851,6 +851,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/api/current.txt b/api/current.txt
index bb40056..db91b9d 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -6450,6 +6450,7 @@
method @Nullable public String[] getAccountTypesWithManagementDisabled();
method @Nullable public java.util.List<android.content.ComponentName> getActiveAdmins();
method @NonNull public java.util.Set<java.lang.String> getAffiliationIds(@NonNull android.content.ComponentName);
+ method @Nullable public java.util.List<java.lang.String> getAlwaysOnVpnLockdownWhitelist(@NonNull android.content.ComponentName);
method @Nullable public String getAlwaysOnVpnPackage(@NonNull android.content.ComponentName);
method @WorkerThread @NonNull public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String);
method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName);
@@ -6519,6 +6520,7 @@
method public boolean isActivePasswordSufficient();
method public boolean isAdminActive(@NonNull android.content.ComponentName);
method public boolean isAffiliatedUser();
+ method public boolean isAlwaysOnVpnLockdownEnabled(@NonNull android.content.ComponentName);
method public boolean isApplicationHidden(@NonNull android.content.ComponentName, String);
method public boolean isBackupServiceEnabled(@NonNull android.content.ComponentName);
method @Deprecated public boolean isCallerApplicationRestrictionsManagingPackage();
@@ -6555,7 +6557,8 @@
method @Nullable public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(@NonNull android.content.ComponentName);
method public void setAccountManagementDisabled(@NonNull android.content.ComponentName, String, boolean);
method public void setAffiliationIds(@NonNull android.content.ComponentName, @NonNull java.util.Set<java.lang.String>);
- method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean) throws android.content.pm.PackageManager.NameNotFoundException, java.lang.UnsupportedOperationException;
+ method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean, @Nullable java.util.List<java.lang.String>) throws android.content.pm.PackageManager.NameNotFoundException;
method public boolean setApplicationHidden(@NonNull android.content.ComponentName, String, boolean);
method @WorkerThread public void setApplicationRestrictions(@Nullable android.content.ComponentName, String, android.os.Bundle);
method @Deprecated public void setApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName, @Nullable String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -11197,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;
@@ -11205,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);
@@ -11268,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);
@@ -41956,8 +41959,8 @@
}
public static final class VideoProfile.CameraCapabilities implements android.os.Parcelable {
- ctor public VideoProfile.CameraCapabilities(int, int);
- ctor public VideoProfile.CameraCapabilities(int, int, boolean, float);
+ ctor public VideoProfile.CameraCapabilities(@IntRange(from=0) int, @IntRange(from=0) int);
+ ctor public VideoProfile.CameraCapabilities(@IntRange(from=0) int, @IntRange(from=0) int, boolean, @FloatRange(from=1.0f) float);
method public int describeContents();
method public int getHeight();
method public float getMaxZoom();
@@ -42217,6 +42220,9 @@
field public static final String KEY_MONTHLY_DATA_CYCLE_DAY_INT = "monthly_data_cycle_day_int";
field public static final String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
field public static final String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
+ field public static final String KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG = "opportunistic_network_data_switch_hysteresis_time_long";
+ field public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_OR_EXIT_HYSTERESIS_TIME_LONG = "opportunistic_network_entry_or_exit_hysteresis_time_long";
+ field public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_BANDWIDTH_INT = "opportunistic_network_entry_threshold_bandwidth_int";
field public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSRP_INT = "opportunistic_network_entry_threshold_rsrp_int";
field public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT = "opportunistic_network_entry_threshold_rssnr_int";
field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT = "opportunistic_network_exit_threshold_rsrp_int";
@@ -42878,6 +42884,7 @@
public class SubscriptionInfo implements android.os.Parcelable {
method public android.graphics.Bitmap createIconBitmap(android.content.Context);
method public int describeContents();
+ method public int getCardId();
method public int getCarrierId();
method public CharSequence getCarrierName();
method public String getCountryIso();
@@ -42994,6 +43001,7 @@
method public android.telephony.TelephonyManager createForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo();
method public int getCallState();
+ method public int getCardIdForDefaultEuicc();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @WorkerThread public android.os.PersistableBundle getCarrierConfig();
method public int getCarrierIdFromSimMccMnc();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.CellLocation getCellLocation();
@@ -43041,6 +43049,7 @@
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getSubscriberId();
method public String getTypeAllocationCode();
method public String getTypeAllocationCode(int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVisualVoicemailPackageName();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailAlphaTag();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber();
@@ -43132,6 +43141,7 @@
field public static final String EXTRA_STATE_RINGING;
field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.extra.SUBSCRIPTION_ID";
field public static final String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER";
+ field public static final int INVALID_CARD_ID = -1; // 0xffffffff
field public static final String METADATA_HIDE_VOICEMAIL_SETTINGS_MENU = "android.telephony.HIDE_VOICEMAIL_SETTINGS_MENU";
field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
@@ -43199,6 +43209,18 @@
method public void onResults(java.util.List<android.telephony.CellInfo>);
}
+ public final class UiccCardInfo implements android.os.Parcelable {
+ ctor public UiccCardInfo(boolean, int, String, String, int);
+ method public int describeContents();
+ method public int getCardId();
+ method public String getEid();
+ method public String getIccId();
+ method public int getSlotIndex();
+ method public boolean isEuicc();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.UiccCardInfo> CREATOR;
+ }
+
public abstract class VisualVoicemailService extends android.app.Service {
ctor public VisualVoicemailService();
method public android.os.IBinder onBind(android.content.Intent);
@@ -55510,13 +55532,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;
}
@@ -55687,12 +55709,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);
@@ -56181,8 +56203,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);
@@ -56192,8 +56214,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);
@@ -57019,45 +57041,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();
@@ -57944,8 +57966,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);
@@ -57957,7 +57979,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);
@@ -57972,8 +57994,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);
@@ -58174,7 +58196,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();
@@ -58272,13 +58294,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 {
@@ -58601,8 +58623,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;
@@ -58610,10 +58632,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>);
}
@@ -58648,20 +58670,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();
@@ -58750,7 +58772,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();
@@ -58793,8 +58815,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();
@@ -58807,7 +58829,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();
}
@@ -58815,9 +58837,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;
}
@@ -58831,7 +58853,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();
}
@@ -58843,8 +58865,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();
}
}
@@ -59888,7 +59910,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();
@@ -59902,8 +59924,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();
@@ -59922,8 +59944,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);
@@ -59937,8 +59959,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 {
@@ -61771,20 +61793,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);
}
@@ -64391,7 +64413,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);
@@ -64631,7 +64653,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);
@@ -66285,8 +66307,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> {
@@ -66395,161 +66417,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 {
@@ -66633,7 +66655,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);
@@ -66721,8 +66743,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;
}
@@ -66733,7 +66755,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);
@@ -66763,12 +66785,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>);
@@ -67286,7 +67308,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);
@@ -67304,8 +67326,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();
@@ -67499,7 +67521,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);
@@ -68164,7 +68186,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);
@@ -68184,7 +68206,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> {
@@ -68575,7 +68597,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>);
@@ -68603,8 +68625,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 {
@@ -70356,7 +70378,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);
@@ -70369,7 +70391,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);
@@ -70385,7 +70407,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);
@@ -70396,8 +70418,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;
@@ -70659,8 +70681,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 4b1d138..0818029 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3088,12 +3088,14 @@
public final class IpPrefix implements android.os.Parcelable {
ctor public IpPrefix(java.net.InetAddress, int);
+ ctor public IpPrefix(String);
}
public class LinkAddress implements android.os.Parcelable {
ctor public LinkAddress(java.net.InetAddress, int, int, int);
ctor public LinkAddress(java.net.InetAddress, int);
ctor public LinkAddress(String);
+ ctor public LinkAddress(String, int, int);
method public boolean isGlobalPreferred();
method public boolean isIPv4();
method public boolean isIPv6();
@@ -3104,6 +3106,7 @@
ctor public LinkProperties();
ctor public LinkProperties(android.net.LinkProperties);
method public boolean addDnsServer(java.net.InetAddress);
+ method public boolean addLinkAddress(android.net.LinkAddress);
method public boolean addRoute(android.net.RouteInfo);
method public void clear();
method @Nullable public android.net.IpPrefix getNat64Prefix();
@@ -3118,6 +3121,7 @@
method public boolean isProvisioned();
method public boolean isReachable(java.net.InetAddress);
method public boolean removeDnsServer(java.net.InetAddress);
+ method public boolean removeLinkAddress(android.net.LinkAddress);
method public boolean removeRoute(android.net.RouteInfo);
method public void setDnsServers(java.util.Collection<java.net.InetAddress>);
method public void setDomains(String);
@@ -3134,6 +3138,7 @@
}
public class Network implements android.os.Parcelable {
+ ctor public Network(android.net.Network);
method public android.net.Network getPrivateDnsBypassingCopy();
}
@@ -3269,8 +3274,8 @@
public class ApfCapabilities {
ctor public ApfCapabilities(int, int, int);
- method public boolean getApfDrop8023Frames(android.content.Context);
- method public int[] getApfEthTypeBlackList(android.content.Context);
+ method public static boolean getApfDrop8023Frames(android.content.Context);
+ method public static int[] getApfEthTypeBlackList(android.content.Context);
method public boolean hasDataAccess();
field public final int apfPacketFormat;
field public final int apfVersionSupported;
@@ -3467,11 +3472,19 @@
package android.net.util {
public class SocketUtils {
+ method public static void addArpEntry(java.net.Inet4Address, android.net.MacAddress, String, java.io.FileDescriptor) throws java.io.IOException;
+ method public static void attachControlPacketFilter(java.io.FileDescriptor, int) throws java.net.SocketException;
+ method public static void attachDhcpFilter(java.io.FileDescriptor) throws java.net.SocketException;
+ method public static void attachRaFilter(java.io.FileDescriptor, int) throws java.net.SocketException;
+ method public static void bindSocket(java.io.FileDescriptor, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
method public static void bindSocketToInterface(java.io.FileDescriptor, String) throws android.system.ErrnoException;
method public static void closeSocket(java.io.FileDescriptor) throws java.io.IOException;
+ method public static void connectSocket(java.io.FileDescriptor, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
method public static java.net.SocketAddress makeNetlinkSocketAddress(int, int);
method public static java.net.SocketAddress makePacketSocketAddress(short, int);
method public static java.net.SocketAddress makePacketSocketAddress(int, byte[]);
+ method public static void sendTo(java.io.FileDescriptor, byte[], int, int, int, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
+ method public static void setSocketTimeValueOption(java.io.FileDescriptor, int, int, long) throws android.system.ErrnoException;
}
}
@@ -6215,7 +6228,6 @@
public class SubscriptionInfo implements android.os.Parcelable {
method @Nullable public java.util.List<android.telephony.UiccAccessRule> getAccessRules();
- method public int getCardId();
method public int getProfileClass();
}
@@ -6275,7 +6287,6 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getCardIdForDefaultEuicc();
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
@@ -6299,7 +6310,6 @@
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getSimLocale();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSupportedRadioAccessFamily();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccCardInfo[] getUiccCardsInfo();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
method @Nullable public android.os.Bundle getVisualVoicemailSettings();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoiceActivationState();
@@ -6308,6 +6318,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();
@@ -6324,6 +6335,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);
@@ -6347,7 +6359,6 @@
field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
- field public static final int INVALID_CARD_ID = -1; // 0xffffffff
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
@@ -6422,18 +6433,6 @@
field public static final android.os.Parcelable.Creator<android.telephony.UiccAccessRule> CREATOR;
}
- public class UiccCardInfo implements android.os.Parcelable {
- ctor public UiccCardInfo(boolean, int, String, String, int);
- method public int describeContents();
- method public int getCardId();
- method public String getEid();
- method public String getIccId();
- method public int getSlotIndex();
- method public boolean isEuicc();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.UiccCardInfo> CREATOR;
- }
-
public class UiccSlotInfo implements android.os.Parcelable {
ctor public UiccSlotInfo(boolean, boolean, String, int, int, boolean);
method public int describeContents();
diff --git a/api/test-current.txt b/api/test-current.txt
index 8403fa5..30c6fdf 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -613,6 +613,7 @@
public final class IpPrefix implements android.os.Parcelable {
ctor public IpPrefix(java.net.InetAddress, int);
+ ctor public IpPrefix(String);
}
public final class IpSecManager {
@@ -621,6 +622,9 @@
public class LinkAddress implements android.os.Parcelable {
ctor public LinkAddress(java.net.InetAddress, int, int, int);
+ ctor public LinkAddress(java.net.InetAddress, int);
+ ctor public LinkAddress(String);
+ ctor public LinkAddress(String, int, int);
method public boolean isGlobalPreferred();
method public boolean isIPv4();
method public boolean isIPv6();
@@ -630,6 +634,7 @@
public final class LinkProperties implements android.os.Parcelable {
ctor public LinkProperties(android.net.LinkProperties);
method public boolean addDnsServer(java.net.InetAddress);
+ method public boolean addLinkAddress(android.net.LinkAddress);
method @Nullable public android.net.IpPrefix getNat64Prefix();
method public java.util.List<java.net.InetAddress> getPcscfServers();
method public String getTcpBufferSizes();
@@ -642,6 +647,7 @@
method public boolean isProvisioned();
method public boolean isReachable(java.net.InetAddress);
method public boolean removeDnsServer(java.net.InetAddress);
+ method public boolean removeLinkAddress(android.net.LinkAddress);
method public boolean removeRoute(android.net.RouteInfo);
method public void setNat64Prefix(android.net.IpPrefix);
method public void setPcscfServers(java.util.Collection<java.net.InetAddress>);
@@ -652,6 +658,7 @@
}
public class Network implements android.os.Parcelable {
+ ctor public Network(android.net.Network);
method public android.net.Network getPrivateDnsBypassingCopy();
}
@@ -703,8 +710,8 @@
public class ApfCapabilities {
ctor public ApfCapabilities(int, int, int);
- method public boolean getApfDrop8023Frames(android.content.Context);
- method public int[] getApfEthTypeBlackList(android.content.Context);
+ method public static boolean getApfDrop8023Frames(android.content.Context);
+ method public static int[] getApfEthTypeBlackList(android.content.Context);
method public boolean hasDataAccess();
field public final int apfPacketFormat;
field public final int apfVersionSupported;
@@ -901,11 +908,19 @@
package android.net.util {
public class SocketUtils {
+ method public static void addArpEntry(java.net.Inet4Address, android.net.MacAddress, String, java.io.FileDescriptor) throws java.io.IOException;
+ method public static void attachControlPacketFilter(java.io.FileDescriptor, int) throws java.net.SocketException;
+ method public static void attachDhcpFilter(java.io.FileDescriptor) throws java.net.SocketException;
+ method public static void attachRaFilter(java.io.FileDescriptor, int) throws java.net.SocketException;
+ method public static void bindSocket(java.io.FileDescriptor, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
method public static void bindSocketToInterface(java.io.FileDescriptor, String) throws android.system.ErrnoException;
method public static void closeSocket(java.io.FileDescriptor) throws java.io.IOException;
+ method public static void connectSocket(java.io.FileDescriptor, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
method public static java.net.SocketAddress makeNetlinkSocketAddress(int, int);
method public static java.net.SocketAddress makePacketSocketAddress(short, int);
method public static java.net.SocketAddress makePacketSocketAddress(int, byte[]);
+ method public static void sendTo(java.io.FileDescriptor, byte[], int, int, int, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
+ method public static void setSocketTimeValueOption(java.io.FileDescriptor, int, int, long) throws android.system.ErrnoException;
}
}
@@ -1775,6 +1790,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/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 3053609..5fd148e 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -23,9 +23,11 @@
import "frameworks/base/cmds/statsd/src/atom_field_options.proto";
import "frameworks/base/core/proto/android/app/enums.proto";
import "frameworks/base/core/proto/android/app/job/enums.proto";
+import "frameworks/base/core/proto/android/bluetooth/a2dp/enums.proto";
import "frameworks/base/core/proto/android/bluetooth/enums.proto";
import "frameworks/base/core/proto/android/bluetooth/hci/enums.proto";
import "frameworks/base/core/proto/android/bluetooth/hfp/enums.proto";
+import "frameworks/base/core/proto/android/bluetooth/smp/enums.proto";
import "frameworks/base/core/proto/android/net/networkcapabilities.proto";
import "frameworks/base/core/proto/android/os/enums.proto";
import "frameworks/base/core/proto/android/server/connectivity/data_stall_event.proto";
@@ -142,6 +144,23 @@
NfcHceTransactionOccurred nfc_hce_transaction_occurred = 139;
SeStateChanged se_state_changed = 140;
SeOmapiReported se_omapi_reported = 141;
+ BluetoothActiveDeviceChanged bluetooth_active_device_changed = 151;
+ BluetoothA2dpPlaybackStateChanged bluetooth_a2dp_playback_state_changed = 152;
+ BluetoothA2dpCodecConfigChanged bluetooth_a2dp_codec_config_changed = 153;
+ BluetoothA2dpCodecCapabilityChanged bluetooth_a2dp_codec_capability_changed = 154;
+ BluetoothA2dpAudioUnderrunReported bluetooth_a2dp_audio_underrun_reported = 155;
+ BluetoothA2dpAudioOverrunReported bluetooth_a2dp_audio_overrun_reported = 156;
+ BluetoothDeviceRssiReported bluetooth_device_rssi_reported = 157;
+ BluetoothDeviceFailedContactCounterReported bluetooth_device_failed_contact_counter_reported = 158;
+ BluetoothDeviceTxPowerLevelReported bluetooth_device_tx_power_level_reported = 159;
+ BluetoothHciTimeoutReported bluetooth_hci_timeout_reported = 160;
+ BluetoothQualityReportReported bluetooth_quality_report_reported = 161;
+ BluetoothManufacturerInfoReported bluetooth_device_info_reported = 162;
+ BluetoothRemoteVersionInfoReported bluetooth_remote_version_info_reported = 163;
+ BluetoothSdpAttributeReported bluetooth_sdp_attribute_reported = 164;
+ BluetoothBondStateChanged bluetooth_bond_state_changed = 165;
+ BluetoothClassicPairingEventReported bluetooth_classic_pairing_event_reported = 166;
+ BluetoothSmpPairingEventReported bluetooth_smp_pairing_event_reported = 167;
}
// Pulled events will start at field 10000.
@@ -1084,6 +1103,27 @@
optional android.bluetooth.hfp.ScoCodec codec = 3;
}
+/**
+ * Logged when active device of a profile changes
+ *
+ * Logged from:
+ * packages/apps/Bluetooth/src/com/android/bluetooth/a2dp/A2dpService.java
+ * packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetService.java
+ * packages/apps/Bluetooth/src/com/android/bluetooth/hearingaid/HearingAidService.java
+ */
+message BluetoothActiveDeviceChanged {
+ // The profile whose active device has changed. Eg. A2DP, HEADSET, HEARING_AID
+ // From android.bluetooth.BluetoothProfile
+ optional int32 bt_profile = 1;
+ // An identifier that can be used to match events for this new active device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ // Size: 32 byte
+ // Default: null or empty if there is no active device for this profile
+ optional bytes obfuscated_id = 2 [(android.os.statsd.log_mode) = MODE_BYTES];
+}
+
// Logs when there is an event affecting Bluetooth device's link layer connection.
// - This event is triggered when there is a related HCI command or event
// - Users of this metrics can deduce Bluetooth device's connection state from these events
@@ -1167,6 +1207,516 @@
optional android.bluetooth.hci.StatusEnum reason_code = 9;
}
+/**
+ * Logs when there is a change in Bluetooth A2DP playback state
+ *
+ * Logged from:
+ * packages/apps/Bluetooth/src/com/android/bluetooth/a2dp/A2dpService.java
+ */
+message BluetoothA2dpPlaybackStateChanged {
+ // An identifier that can be used to match events for this device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ // Size: 32 byte
+ // Default: null or empty if the device identifier is not known
+ optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // Current playback state
+ // Default: PLAYBACK_STATE_UNKNOWN
+ optional android.bluetooth.a2dp.PlaybackStateEnum playback_state = 2;
+ // Current audio coding mode
+ // Default: AUDIO_CODING_MODE_UNKNOWN
+ optional android.bluetooth.a2dp.AudioCodingModeEnum audio_coding_mode = 3;
+}
+
+/**
+ * Logs when there is a change in A2DP codec config for a particular remote device
+ *
+ * Logged from:
+ * frameworks/base/core/java/android/bluetooth/BluetoothCodecConfig.java
+ * packages/apps/Bluetooth/src/com/android/bluetooth/a2dp/A2dpService.java
+ */
+message BluetoothA2dpCodecConfigChanged {
+ // An identifier that can be used to match events for this device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ // Size: 32 byte
+ // Default: null or empty if the device identifier is not known
+ optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // Type of codec as defined by various SOURCE_CODEC_TYPE_* constants in BluetoothCodecConfig
+ // Default SOURCE_CODEC_TYPE_INVALID
+ optional int32 codec_type = 2;
+ // Codec priroity, the higher the more preferred, -1 for disabled
+ // Default: CODEC_PRIORITY_DEFAULT
+ optional int32 codec_priority = 3;
+ // Sample rate in Hz as defined by various SAMPLE_RATE_* constants in BluetoothCodecConfig
+ // Default: SAMPLE_RATE_NONE
+ optional int32 sample_rate = 4;
+ // Bits per sample as defined by various BITS_PER_SAMPLE_* constants in BluetoothCodecConfig
+ // Default: BITS_PER_SAMPLE_NONE
+ optional int32 bits_per_sample = 5;
+ // Channel mode as defined by various CHANNEL_MODE_* constants in BluetoothCodecConfig
+ // Default: CHANNEL_MODE_NONE
+ optional int32 channel_mode = 6;
+ // Codec specific values
+ // Default 0
+ optional int64 codec_specific_1 = 7;
+ optional int64 codec_specific_2 = 8;
+ optional int64 codec_specific_3 = 9;
+ optional int64 codec_specific_4 = 10;
+}
+
+/**
+ * Logs when there is a change in selectable A2DP codec capability for a paricular remote device
+ * Each codec's capability is logged separately due to statsd restriction
+ *
+ * Logged from:
+ * frameworks/base/core/java/android/bluetooth/BluetoothCodecConfig.java
+ * packages/apps/Bluetooth/src/com/android/bluetooth/a2dp/A2dpService.java
+ */
+message BluetoothA2dpCodecCapabilityChanged {
+ // An identifier that can be used to match events for this device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ // Size: 32 byte
+ // Default: null or empty if the device identifier is not known
+ optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // Type of codec as defined by various SOURCE_CODEC_TYPE_* constants in BluetoothCodecConfig
+ // Default SOURCE_CODEC_TYPE_INVALID
+ optional int32 codec_type = 2;
+ // Codec priroity, the higher the more preferred, -1 for disabled
+ // Default: CODEC_PRIORITY_DEFAULT
+ optional int32 codec_priority = 3;
+ // A bit field of supported sample rates as defined by various SAMPLE_RATE_* constants
+ // in BluetoothCodecConfig
+ // Default: empty and SAMPLE_RATE_NONE for individual item
+ optional int32 sample_rate = 4;
+ // A bit field of supported bits per sample as defined by various BITS_PER_SAMPLE_* constants
+ // in BluetoothCodecConfig
+ // Default: empty and BITS_PER_SAMPLE_NONE for individual item
+ optional int32 bits_per_sample = 5;
+ // A bit field of supported channel mode as defined by various CHANNEL_MODE_* constants in
+ // BluetoothCodecConfig
+ // Default: empty and CHANNEL_MODE_NONE for individual item
+ optional int32 channel_mode = 6;
+ // Codec specific values
+ // Default 0
+ optional int64 codec_specific_1 = 7;
+ optional int64 codec_specific_2 = 8;
+ optional int64 codec_specific_3 = 9;
+ optional int64 codec_specific_4 = 10;
+}
+
+/**
+ * Logs when A2DP failed to read from PCM source.
+ * This typically happens when audio HAL cannot supply A2DP with data fast enough for encoding.
+ *
+ * Logged from:
+ * system/bt
+ */
+message BluetoothA2dpAudioUnderrunReported {
+ // An identifier that can be used to match events for this device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ // Size: 32 byte
+ // Default: null or empty if the device identifier is not known
+ optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // Encoding interval in nanoseconds
+ // Default: 0
+ optional int64 encoding_interval_nanos = 2;
+ // Number of bytes of PCM data that could not be read from the source
+ // Default: 0
+ optional int32 num_missing_pcm_bytes = 3;
+}
+
+/**
+ * Logs when A2DP failed send encoded data to the remote device fast enough such that the transmit
+ * buffer queue is full and we have to drop data
+ *
+ * Logged from:
+ * system/bt
+ */
+message BluetoothA2dpAudioOverrunReported {
+ // An identifier that can be used to match events for this device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ // Size: 32 byte
+ // Default: null or empty if the device identifier is not known
+ optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // Encoding interval in nanoseconds
+ // Default: 0
+ optional int64 encoding_interval_nanos = 2;
+ // Number of buffers dropped in this event
+ // Each buffer is encoded in one encoding interval and consists of multiple encoded frames
+ // Default: 0
+ optional int32 num_dropped_buffers = 3;
+ // Number of encoded buffers dropped in this event
+ // Default 0
+ optional int32 num_dropped_encoded_frames = 4;
+ // Number of encoded bytes dropped in this event
+ // Default: 0
+ optional int32 num_dropped_encoded_bytes = 5;
+}
+
+/**
+ * Logs when we receive reports regarding a device's RSSI value
+ *
+ * Logged from:
+ * system/bt
+ */
+message BluetoothDeviceRssiReported {
+ // An identifier that can be used to match events for this device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ // Size: 32 byte
+ // Default: null or empty if the device identifier is not known
+ optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // Connection handle of this connection if available
+ // Range: 0x0000 - 0x0EFF (12 bits)
+ // Default: 0xFFFF if the handle is unknown
+ optional int32 connection_handle = 2;
+ // HCI command status code if this is triggerred by hci_cmd
+ // Default: STATUS_UNKNOWN
+ optional android.bluetooth.hci.StatusEnum hci_status = 3;
+ // BR/EDR
+ // Range: -128 ≤ N ≤ 127 (signed integer)
+ // Units: dB
+ // LE:
+ // Range: -127 to 20, 127 (signed integer)
+ // Units: dBm
+ // Invalid when an out of range value is reported
+ optional int32 rssi = 4;
+}
+
+/**
+ * Logs when we receive reports regarding how many consecutive failed contacts for a connection
+ *
+ * Logged from:
+ * system/bt
+ */
+message BluetoothDeviceFailedContactCounterReported {
+ // An identifier that can be used to match events for this device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ // Size: 32 byte
+ // Default: null or empty if the device identifier is not known
+ optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // Connection handle of this connection if available
+ // Range: 0x0000 - 0x0EFF (12 bits)
+ // Default: 0xFFFF if the handle is unknown
+ optional int32 connection_handle = 2;
+ // HCI command status code if this is triggerred by hci_cmd
+ // Default: STATUS_UNKNOWN
+ optional android.bluetooth.hci.StatusEnum cmd_status = 3;
+ // Number of consecutive failed contacts for a connection corresponding to the Handle
+ // Range: uint16_t, 0-0xFFFF
+ // Default: 0xFFFFF
+ optional int32 failed_contact_counter = 4;
+}
+
+/**
+ * Logs when we receive reports regarding the tranmit power level used for a specific connection
+ *
+ * Logged from:
+ * system/bt
+ */
+message BluetoothDeviceTxPowerLevelReported {
+ // An identifier that can be used to match events for this device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ // Size: 32 byte
+ // Default: null or empty if the device identifier is not known
+ optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // Connection handle of this connection if available
+ // Range: 0x0000 - 0x0EFF (12 bits)
+ // Default: 0xFFFF if the handle is unknown
+ optional int32 connection_handle = 2;
+ // HCI command status code if this is triggered by hci_cmd
+ // Default: STATUS_UNKNOWN
+ optional android.bluetooth.hci.StatusEnum hci_status = 3;
+ // Range: -30 ≤ N ≤ 20
+ // Units: dBm
+ // Invalid when an out of range value is reported
+ optional int32 transmit_power_level = 4;
+}
+
+/**
+ * Logs when Bluetooth controller failed to reply with command status within a timeout period after
+ * receiving an HCI command from the host
+ *
+ * Logged from: system/bt
+ */
+message BluetoothHciTimeoutReported {
+ // HCI command associated with this event
+ // Default: CMD_UNKNOWN
+ optional android.bluetooth.hci.CommandEnum hci_command = 1;
+}
+
+/**
+ * Logs when we receive Bluetooth Link Quality Report event from the controller
+ * See Android Bluetooth HCI specification for more details
+ *
+ * Note: all count and bytes field are counted since last event
+ *
+ * Logged from: system/bt
+ */
+message BluetoothQualityReportReported {
+ // Quality report ID
+ // Original type: uint8_t
+ // Default: BQR_ID_UNKNOWN
+ optional android.bluetooth.hci.BqrIdEnum quality_report_id = 1;
+ // Packet type of the connection
+ // Original type: uint8_t
+ // Default: BQR_PACKET_TYPE_UNKNOWN
+ optional android.bluetooth.hci.BqrPacketTypeEnum packet_types = 2;
+ // Connection handle of the connection
+ // Original type: uint16_t
+ optional int32 connection_handle = 3;
+ // Performing Role for the connection
+ // Original type: uint8_t
+ optional int32 connection_role = 4;
+ // Current Transmit Power Level for the connection. This value is the same as the controller's
+ // response to the HCI_Read_Transmit_Power_Level HCI command
+ // Original type: uint8_t
+ optional int32 tx_power_level = 5;
+ // Received Signal Strength Indication (RSSI) value for the connection. This value is an
+ // absolute receiver signal strength value
+ // Original type: int8_t
+ optional int32 rssi = 6;
+ // Signal-to-Noise Ratio (SNR) value for the connection. It is the average SNR of all the
+ // channels used by the link currently
+ // Original type: uint8_t
+ optional int32 snr = 7;
+ // Indicates the number of unused channels in AFH_channel_map
+ // Original type: uint8_t
+ optional int32 unused_afh_channel_count = 8;
+ // Indicates the number of the channels which are interfered and quality is bad but are still
+ // selected for AFH
+ // Original type: uint8_t
+ optional int32 afh_select_unideal_channel_count = 9;
+ // Current Link Supervision Timeout Setting
+ // Unit: N * 0.3125 ms (1 Bluetooth Clock)
+ // Original type: uint16_t
+ optional int32 lsto = 10;
+ // Piconet Clock for the specified Connection_Handle. This value is the same as the controller's
+ // response to HCI_Read_Clock HCI command with the parameter "Which_Clock" of
+ // 0x01 (Piconet Clock)
+ // Unit: N * 0.3125 ms (1 Bluetooth Clock)
+ // Original type: uint32_t
+ optional int64 connection_piconet_clock = 11;
+ // The count of retransmission
+ // Original type: uint32_t
+ optional int64 retransmission_count = 12;
+ // The count of no RX
+ // Original type: uint32_t
+ optional int64 no_rx_count = 13;
+ // The count of NAK (Negative Acknowledge)
+ // Original type: uint32_t
+ optional int64 nak_count = 14;
+ // Controller timestamp of last TX ACK
+ // Unit: N * 0.3125 ms (1 Bluetooth Clock)
+ // Original type: uint32_t
+ optional int64 last_tx_ack_timestamp = 15;
+ // The count of Flow-off (STOP)
+ // Original type: uint32_t
+ optional int64 flow_off_count = 16;
+ // Controller timestamp of last Flow-on (GO)
+ // Unit: N * 0.3125 ms (1 Bluetooth Clock)
+ // Original type: uint32_t
+ optional int64 last_flow_on_timestamp = 17;
+ // Buffer overflow count (how many bytes of TX data are dropped) since the last event
+ // Original type: uint32_t
+ optional int64 buffer_overflow_bytes = 18;
+ // Buffer underflow count (in byte) since last event
+ // Original type: uint32_t
+ optional int64 buffer_underflow_bytes = 19;
+}
+
+/**
+ * Logs when a Bluetooth device's manufacturer information is learnt by the Bluetooth stack
+ *
+ * Notes:
+ * - Each event can be partially filled as we might learn different pieces of device
+ * information at different time
+ * - Multiple device info events can be combined to give more complete picture
+ * - When multiple device info events tries to describe the same information, the
+ * later one wins
+ *
+ * Logged from:
+ * packages/apps/Bluetooth
+ */
+message BluetoothManufacturerInfoReported {
+ // An identifier that can be used to match events for this device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ // Size: 32 byte
+ // Default: null or empty if the device identifier is not known
+ optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // Where is this device info obtained from
+ optional android.bluetooth.DeviceInfoSrcEnum source_type = 2;
+ // Name of the data source
+ // For EXTERNAL: package name of the data source
+ // For INTERNAL: null for general case, component name otherwise
+ optional string source_name = 3;
+ // Name of the manufacturer of this device
+ optional string manufacturer = 4;
+ // Model of this device
+ optional string model = 5;
+ // Hardware version of this device
+ optional string hardware_version = 6;
+ // Software version of this device
+ optional string software_version = 7;
+}
+
+/**
+ * Logs when we receive Bluetooth Read Remote Version Information Complete Event from the remote
+ * device, as documented by the Bluetooth Core HCI specification
+ * Reference: https://www.bluetooth.com/specifications/bluetooth-core-specification
+ * Vol 2, Part E, Page 1118
+ *
+ * Logged from:
+ * system/bt
+ */
+message BluetoothRemoteVersionInfoReported {
+ // Connection handle of the connection
+ // Original type: uint16_t
+ optional int32 connection_handle = 1;
+ // HCI command status code
+ // Default: STATUS_UNKNOWN
+ optional android.bluetooth.hci.StatusEnum hci_status = 2;
+ // 1 byte Version of current LMP in the remote controller
+ optional int32 lmp_version = 3;
+ // 2 bytes LMP manufacturer code of the remote controller
+ // https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
+ optional int32 lmp_manufacturer_code = 4;
+ // 4 bytes subversion of the LMP in the remote controller
+ optional int32 lmp_subversion = 5;
+}
+
+/**
+ * Logs when certain Bluetooth SDP attributes are discovered
+ * Constant definitions are from:
+ * https://www.bluetooth.com/specifications/assigned-numbers/service-discovery
+ *
+ * Current logged attributes:
+ * - BluetoothProfileDescriptorList
+ * - Supported Features Bitmask
+ *
+ * Logged from:
+ * system/bt
+ */
+message BluetoothSdpAttributeReported {
+ // An identifier that can be used to match events for this device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // Short form UUIDs used to identify Bluetooth protocols, profiles, and service classes
+ // Original type: uint16_t
+ optional int32 protocol_uuid = 2;
+ // Short form UUIDs used to identify Bluetooth SDP attribute types
+ // Original type: uint16_t
+ optional int32 attribute_id = 3;
+ // Attribute value for the particular attribute
+ optional bytes attribute_value = 4 [(android.os.statsd.log_mode) = MODE_BYTES];
+}
+
+/**
+ * Logs when bond state of a Bluetooth device changes
+ *
+ * Logged from:
+ * frameworks/base/core/java/android/bluetooth/BluetoothDevice.java
+ * packages/apps/Bluetooth/src/com/android/bluetooth/btservice/BondStateMachine.java
+ */
+message BluetoothBondStateChanged {
+ // An identifier that can be used to match events for this device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ // Size: 32 byte
+ // Default: null or empty if the device identifier is not known
+ optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // Preferred transport type to remote dual mode device
+ // Default: TRANSPORT_AUTO means no preference
+ optional android.bluetooth.TransportTypeEnum transport = 2;
+ // The type of this Bluetooth device (Classic, LE, or Dual mode)
+ // Default: UNKNOWN
+ optional android.bluetooth.DeviceTypeEnum type = 3;
+ // Current bond state (NONE, BONDING, BONDED)
+ // Default: BOND_STATE_UNKNOWN
+ optional android.bluetooth.BondStateEnum bond_state = 4;
+ // Bonding sub state
+ // Default: BOND_SUB_STATE_UNKNOWN
+ optional android.bluetooth.BondSubStateEnum bonding_sub_state = 5;
+ // Unbond Reason
+ // Default: UNBOND_REASON_UNKNOWN
+ optional android.bluetooth.UnbondReasonEnum unbond_reason = 6;
+}
+
+/**
+ * Logs there is an event related Bluetooth classic pairing
+ *
+ * Logged from:
+ * system/bt
+ */
+message BluetoothClassicPairingEventReported {
+ // An identifier that can be used to match events for this device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ // Size: 32 byte
+ // Default: null or empty if the device identifier is not known
+ optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // Connection handle of this connection if available
+ // Range: 0x0000 - 0x0EFF (12 bits)
+ // Default: 0xFFFF if the handle is unknown
+ optional int32 connection_handle = 2;
+ // HCI command associated with this event
+ // Default: CMD_UNKNOWN
+ optional android.bluetooth.hci.CommandEnum hci_cmd = 3;
+ // HCI event associated with this event
+ // Default: EVT_UNKNOWN
+ optional android.bluetooth.hci.EventEnum hci_event = 4;
+ // HCI command status code if this is triggerred by hci_cmd
+ // Default: STATUS_UNKNOWN
+ optional android.bluetooth.hci.StatusEnum cmd_status = 5;
+ // HCI reason code associated with this event
+ // Default: STATUS_UNKNOWN
+ optional android.bluetooth.hci.StatusEnum reason_code = 6;
+}
+
+/**
+ * Logs when there is an event related to Bluetooth Security Manager Protocol (SMP)
+ *
+ * Logged from:
+ * system/bt
+ */
+message BluetoothSmpPairingEventReported {
+ // An identifier that can be used to match events for this device.
+ // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+ // Salt: Randomly generated 256 bit value
+ // Hash algorithm: HMAC-SHA256
+ // Size: 32 byte
+ // Default: null or empty if the device identifier is not known
+ optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // SMP command sent or received over L2CAP
+ // Default: CMD_UNKNOWN
+ optional android.bluetooth.smp.CommandEnum smp_command = 2;
+ // Whether this command is sent or received
+ // Default: DIRECTION_UNKNOWN
+ optional android.bluetooth.DirectionEnum direction = 3;
+ // SMP failure reason code
+ // Default: PAIRING_FAIL_REASON_DEFAULT
+ optional android.bluetooth.smp.PairingFailReasonEnum smp_fail_reason = 4;
+}
/**
* Logs when something is plugged into or removed from the USB-C connector.
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 1b08ecd..18a006f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -4464,11 +4464,16 @@
}
/**
+ * Service-specific error code used in implementation of {@code setAlwaysOnVpnPackage} methods.
+ * @hide
+ */
+ public static final int ERROR_VPN_PACKAGE_NOT_FOUND = 1;
+
+ /**
* Called by a device or profile owner to configure an always-on VPN connection through a
* specific application for the current user. This connection is automatically granted and
* persisted after a reboot.
- * <p>
- * To support the always-on feature, an app must
+ * <p> To support the always-on feature, an app must
* <ul>
* <li>declare a {@link android.net.VpnService} in its manifest, guarded by
* {@link android.Manifest.permission#BIND_VPN_SERVICE};</li>
@@ -4477,25 +4482,61 @@
* {@link android.net.VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON}.</li>
* </ul>
* The call will fail if called with the package name of an unsupported VPN app.
+ * <p> Enabling lockdown via {@code lockdownEnabled} argument carries the risk that any failure
+ * of the VPN provider could break networking for all apps.
*
* @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. This carries the risk that any failure of the VPN provider
- * could break networking for all apps. This has no effect when clearing.
+ * {@code false} otherwise. This has no effect when clearing.
* @throws SecurityException if {@code admin} is not a device or a profile owner.
* @throws NameNotFoundException if {@code vpnPackage} is not installed.
* @throws UnsupportedOperationException if {@code vpnPackage} exists but does not support being
* set as always-on, or if always-on VPN is not available.
+ * @see #setAlwaysOnVpnPackage(ComponentName, String, boolean, List)
*/
public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage,
- boolean lockdownEnabled)
- throws NameNotFoundException, UnsupportedOperationException {
+ boolean lockdownEnabled) throws NameNotFoundException {
+ setAlwaysOnVpnPackage(admin, vpnPackage, lockdownEnabled, Collections.emptyList());
+ }
+
+ /**
+ * A version of {@link #setAlwaysOnVpnPackage(ComponentName, String, boolean)} that allows the
+ * admin to specify a set of apps that should be able to access the network directly when VPN
+ * is not connected. When VPN connects these apps switch over to VPN if allowed to use that VPN.
+ * System apps can always bypass VPN.
+ * <p> Note that the system doesn't update the whitelist when packages are installed or
+ * uninstalled, the admin app must call this method to keep the list up to date.
+ *
+ * @param vpnPackage 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. This has no effect when clearing.
+ * @param lockdownWhitelist Packages that will be able to access the network directly when VPN
+ * is in lockdown mode but not connected. Has no effect when clearing.
+ * @throws SecurityException if {@code admin} is not a device or a profile
+ * owner.
+ * @throws NameNotFoundException if {@code vpnPackage} or one of
+ * {@code lockdownWhitelist} is not installed.
+ * @throws UnsupportedOperationException if {@code vpnPackage} exists but does
+ * not support being set as always-on, or if always-on VPN is not
+ * available.
+ */
+ public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage,
+ boolean lockdownEnabled, @Nullable List<String> lockdownWhitelist)
+ throws NameNotFoundException {
throwIfParentInstance("setAlwaysOnVpnPackage");
if (mService != null) {
try {
- if (!mService.setAlwaysOnVpnPackage(admin, vpnPackage, lockdownEnabled)) {
- throw new NameNotFoundException(vpnPackage);
+ mService.setAlwaysOnVpnPackage(
+ admin, vpnPackage, lockdownEnabled, lockdownWhitelist);
+ } catch (ServiceSpecificException e) {
+ switch (e.errorCode) {
+ case ERROR_VPN_PACKAGE_NOT_FOUND:
+ throw new NameNotFoundException(e.getMessage());
+ default:
+ throw new RuntimeException(
+ "Unknown error setting always-on VPN: " + e.errorCode, e);
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -4504,6 +4545,51 @@
}
/**
+ * Called by device or profile owner to query whether current always-on VPN is configured in
+ * lockdown mode. Returns {@code false} when no always-on configuration is set.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ *
+ * @throws SecurityException if {@code admin} is not a device or a profile owner.
+ *
+ * @see #setAlwaysOnVpnPackage(ComponentName, String, boolean)
+ */
+ public boolean isAlwaysOnVpnLockdownEnabled(@NonNull ComponentName admin) {
+ throwIfParentInstance("isAlwaysOnVpnLockdownEnabled");
+ if (mService != null) {
+ try {
+ return mService.isAlwaysOnVpnLockdownEnabled(admin);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Called by device or profile owner to query the list of packages that are allowed to access
+ * the network directly when always-on VPN is in lockdown mode but not connected. Returns
+ * {@code null} when always-on VPN is not active or not in lockdown mode.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ *
+ * @throws SecurityException if {@code admin} is not a device or a profile owner.
+ *
+ * @see #setAlwaysOnVpnPackage(ComponentName, String, boolean, List)
+ */
+ public @Nullable List<String> getAlwaysOnVpnLockdownWhitelist(@NonNull ComponentName admin) {
+ throwIfParentInstance("getAlwaysOnVpnLockdownWhitelist");
+ if (mService != null) {
+ try {
+ return mService.getAlwaysOnVpnLockdownWhitelist(admin);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return null;
+ }
+
+ /**
* Called by a device or profile owner to read the name of the package administering an
* always-on VPN connection for the current user. If there is no such package, or the always-on
* VPN is provided by the system instead of by an application, {@code null} will be returned.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 37508cd..0046302 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -182,8 +182,10 @@
void setCertInstallerPackage(in ComponentName who, String installerPackage);
String getCertInstallerPackage(in ComponentName who);
- boolean setAlwaysOnVpnPackage(in ComponentName who, String vpnPackage, boolean lockdown);
+ boolean setAlwaysOnVpnPackage(in ComponentName who, String vpnPackage, boolean lockdown, in List<String> lockdownWhitelist);
String getAlwaysOnVpnPackage(in ComponentName who);
+ boolean isAlwaysOnVpnLockdownEnabled(in ComponentName who);
+ List<String> getAlwaysOnVpnLockdownWhitelist(in ComponentName who);
void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);
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/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/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/IpPrefix.java b/core/java/android/net/IpPrefix.java
index b996cda..175263f 100644
--- a/core/java/android/net/IpPrefix.java
+++ b/core/java/android/net/IpPrefix.java
@@ -104,6 +104,8 @@
*
* @hide
*/
+ @SystemApi
+ @TestApi
public IpPrefix(String prefix) {
// We don't reuse the (InetAddress, int) constructor because "error: call to this must be
// first statement in constructor". We could factor out setting the member variables to an
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index fbd602c..8d779aa 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -176,6 +176,7 @@
* @hide
*/
@SystemApi
+ @TestApi
public LinkAddress(InetAddress address, int prefixLength) {
this(address, prefixLength, 0, 0);
this.scope = scopeForUnicastAddress(address);
@@ -199,6 +200,7 @@
* @hide
*/
@SystemApi
+ @TestApi
public LinkAddress(String address) {
this(address, 0, 0);
this.scope = scopeForUnicastAddress(this.address);
@@ -212,6 +214,8 @@
* @param scope The address scope.
* @hide
*/
+ @SystemApi
+ @TestApi
public LinkAddress(String address, int flags, int scope) {
// This may throw an IllegalArgumentException; catching it is the caller's responsibility.
// TODO: consider rejecting mapped IPv4 addresses such as "::ffff:192.0.2.5/24".
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 6628701..42db0fd 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -287,7 +287,8 @@
* @return true if {@code address} was added or updated, false otherwise.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @TestApi
public boolean addLinkAddress(LinkAddress address) {
if (address == null) {
return false;
@@ -315,6 +316,8 @@
* @return true if the address was removed, false if it did not exist.
* @hide
*/
+ @SystemApi
+ @TestApi
public boolean removeLinkAddress(LinkAddress toRemove) {
int i = findLinkAddressIndex(toRemove);
if (i >= 0) {
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 2c831de..e04b5fc 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -123,6 +123,8 @@
/**
* @hide
*/
+ @SystemApi
+ @TestApi
public Network(Network that) {
this(that.netId, that.mPrivateDnsBypass);
}
diff --git a/core/java/android/net/NetworkStack.java b/core/java/android/net/NetworkStack.java
index d277034..ac6bff0 100644
--- a/core/java/android/net/NetworkStack.java
+++ b/core/java/android/net/NetworkStack.java
@@ -104,10 +104,11 @@
*
* <p>The INetworkMonitor will be returned asynchronously through the provided callbacks.
*/
- 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();
}
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/apf/ApfCapabilities.java b/core/java/android/net/apf/ApfCapabilities.java
index baf5585..e09fa8f 100644
--- a/core/java/android/net/apf/ApfCapabilities.java
+++ b/core/java/android/net/apf/ApfCapabilities.java
@@ -81,14 +81,14 @@
/**
* @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames.
*/
- public boolean getApfDrop8023Frames(Context context) {
+ public static boolean getApfDrop8023Frames(Context context) {
return context.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);
}
/**
* @return An array of blacklisted EtherType, packets with EtherTypes within it will be dropped.
*/
- public int[] getApfEthTypeBlackList(Context context) {
+ public static int[] getApfEthTypeBlackList(Context context) {
return context.getResources().getIntArray(R.array.config_apfEthTypeBlackList);
}
}
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/packages/NetworkStack/src/android/net/util/FdEventsReader.java b/core/java/android/net/shared/FdEventsReader.java
similarity index 89%
rename from packages/NetworkStack/src/android/net/util/FdEventsReader.java
rename to core/java/android/net/shared/FdEventsReader.java
index 8bbf449..bffbfb1 100644
--- a/packages/NetworkStack/src/android/net/util/FdEventsReader.java
+++ b/core/java/android/net/shared/FdEventsReader.java
@@ -14,22 +14,22 @@
* limitations under the License.
*/
-package android.net.util;
+package android.net.shared;
-import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
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;
/**
@@ -63,6 +63,7 @@
* All public methods MUST only be called from the same thread with which
* the Handler constructor argument is associated.
*
+ * @param <BufferType> the type of the buffer used to read data.
* @hide
*/
public abstract class FdEventsReader<BufferType> {
@@ -80,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) {
@@ -89,6 +93,7 @@
mBuffer = buffer;
}
+ /** Start this FdEventsReader. */
public void start() {
if (onCorrectThread()) {
createAndRegisterFd();
@@ -100,6 +105,7 @@
}
}
+ /** Stop this FdEventsReader and destroy the file descriptor. */
public void stop() {
if (onCorrectThread()) {
unregisterAndDestroyFd();
@@ -112,22 +118,29 @@
}
@NonNull
- public Handler getHandler() { return mHandler; }
+ public Handler getHandler() {
+ return mHandler;
+ }
protected abstract int recvBufSize(@NonNull BufferType buffer);
- public int recvBufSize() { return recvBufSize(mBuffer); }
+ /** Returns the size of the receive buffer. */
+ public int recvBufSize() {
+ return recvBufSize(mBuffer);
+ }
/**
* Get the number of successful calls to {@link #readPacket(FileDescriptor, Object)}.
*
* <p>A call was successful if {@link #readPacket(FileDescriptor, Object)} returned a value > 0.
*/
- public final long numPacketsReceived() { return mPacketsReceived; }
+ public final long numPacketsReceived() {
+ return mPacketsReceived;
+ }
/**
- * 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();
@@ -171,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);
@@ -199,7 +208,9 @@
onStart();
}
- private boolean isRunning() { return (mFd != null) && mFd.valid(); }
+ private boolean isRunning() {
+ return (mFd != null) && mFd.valid();
+ }
// Keep trying to read until we get EAGAIN/EWOULDBLOCK or some fatal error.
private boolean handleInput() {
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/net/util/SocketUtils.java b/core/java/android/net/util/SocketUtils.java
index 2df08a1..fbb15ed 100644
--- a/core/java/android/net/util/SocketUtils.java
+++ b/core/java/android/net/util/SocketUtils.java
@@ -21,17 +21,21 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.net.MacAddress;
import android.net.NetworkUtils;
import android.system.ErrnoException;
import android.system.NetlinkSocketAddress;
import android.system.Os;
import android.system.PacketSocketAddress;
+import android.system.StructTimeval;
import libcore.io.IoBridge;
import java.io.FileDescriptor;
import java.io.IOException;
+import java.net.Inet4Address;
import java.net.SocketAddress;
+import java.net.SocketException;
/**
* Collection of utilities to interact with raw sockets.
@@ -76,11 +80,80 @@
}
/**
+ * Set an option on a socket that takes a time value argument.
+ */
+ public static void setSocketTimeValueOption(
+ FileDescriptor fd, int level, int option, long millis) throws ErrnoException {
+ Os.setsockoptTimeval(fd, level, option, StructTimeval.fromMillis(millis));
+ }
+
+ /**
+ * Bind a socket to the specified address.
+ */
+ public static void bindSocket(FileDescriptor fd, SocketAddress addr)
+ throws ErrnoException, SocketException {
+ Os.bind(fd, addr);
+ }
+
+ /**
+ * Connect a socket to the specified address.
+ */
+ public static void connectSocket(FileDescriptor fd, SocketAddress addr)
+ throws ErrnoException, SocketException {
+ Os.connect(fd, addr);
+ }
+
+ /**
+ * Send a message on a socket, using the specified SocketAddress.
+ */
+ public static void sendTo(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount,
+ int flags, SocketAddress addr) throws ErrnoException, SocketException {
+ Os.sendto(fd, bytes, byteOffset, byteCount, flags, addr);
+ }
+
+ /**
* @see IoBridge#closeAndSignalBlockedThreads(FileDescriptor)
*/
public static void closeSocket(FileDescriptor fd) throws IOException {
IoBridge.closeAndSignalBlockedThreads(fd);
}
+ /**
+ * Attaches a socket filter that accepts DHCP packets to the given socket.
+ */
+ public static void attachDhcpFilter(FileDescriptor fd) throws SocketException {
+ NetworkUtils.attachDhcpFilter(fd);
+ }
+
+ /**
+ * Attaches a socket filter that accepts ICMPv6 router advertisements to the given socket.
+ * @param fd the socket's {@link FileDescriptor}.
+ * @param packetType the hardware address type, one of ARPHRD_*.
+ */
+ public static void attachRaFilter(FileDescriptor fd, int packetType) throws SocketException {
+ NetworkUtils.attachRaFilter(fd, packetType);
+ }
+
+ /**
+ * Attaches a socket filter that accepts L2-L4 signaling traffic required for IP connectivity.
+ *
+ * This includes: all ARP, ICMPv6 RS/RA/NS/NA messages, and DHCPv4 exchanges.
+ *
+ * @param fd the socket's {@link FileDescriptor}.
+ * @param packetType the hardware address type, one of ARPHRD_*.
+ */
+ public static void attachControlPacketFilter(FileDescriptor fd, int packetType)
+ throws SocketException {
+ NetworkUtils.attachControlPacketFilter(fd, packetType);
+ }
+
+ /**
+ * Add an entry into the ARP cache.
+ */
+ public static void addArpEntry(Inet4Address ipv4Addr, MacAddress ethAddr, String ifname,
+ FileDescriptor fd) throws IOException {
+ NetworkUtils.addArpEntry(ipv4Addr, ethAddr, ifname, fd);
+ }
+
private SocketUtils() {}
}
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/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/proto/Android.bp b/core/proto/Android.bp
index 80cc2d4..3b891d6 100644
--- a/core/proto/Android.bp
+++ b/core/proto/Android.bp
@@ -21,7 +21,10 @@
type: "lite",
},
srcs: [
+ "android/bluetooth/a2dp/enums.proto",
"android/bluetooth/enums.proto",
"android/bluetooth/hci/enums.proto",
+ "android/bluetooth/hfp/enums.proto",
+ "android/bluetooth/smp/enums.proto",
],
}
diff --git a/core/proto/android/bluetooth/a2dp/enums.proto b/core/proto/android/bluetooth/a2dp/enums.proto
new file mode 100644
index 0000000..5a025bd
--- /dev/null
+++ b/core/proto/android/bluetooth/a2dp/enums.proto
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.bluetooth.a2dp;
+
+option java_outer_classname = "BluetoothA2dpProtoEnums";
+option java_multiple_files = true;
+
+// A2dp playback state enum, defined from:
+// frameworks/base/core/java/android/bluetooth/BluetoothA2dp.java
+enum PlaybackStateEnum {
+ PLAYBACK_STATE_UNKNOWN = 0;
+ PLAYBACK_STATE_PLAYING = 10;
+ PLAYBACK_STATE_NOT_PLAYING = 11;
+}
+
+enum AudioCodingModeEnum {
+ AUDIO_CODING_MODE_UNKNOWN = 0;
+ AUDIO_CODING_MODE_HARDWARE = 1;
+ AUDIO_CODING_MODE_SOFTWARE = 2;
+}
diff --git a/core/proto/android/bluetooth/enums.proto b/core/proto/android/bluetooth/enums.proto
index 76c240e..a88a06c 100644
--- a/core/proto/android/bluetooth/enums.proto
+++ b/core/proto/android/bluetooth/enums.proto
@@ -56,3 +56,57 @@
LINK_TYPE_ACL = 0x01;
LINK_TYPE_ESCO = 0x02;
}
+
+enum DeviceInfoSrcEnum {
+ DEVICE_INFO_SRC_UNKNOWN = 0;
+ // Within Android Bluetooth stack
+ DEVICE_INFO_INTERNAL = 1;
+ // Outside Android Bluetooth stack
+ DEVICE_INFO_EXTERNAL = 2;
+}
+
+enum DeviceTypeEnum {
+ DEVICE_TYPE_UNKNOWN = 0;
+ DEVICE_TYPE_CLASSIC = 1;
+ DEVICE_TYPE_LE = 2;
+ DEVICE_TYPE_DUAL = 3;
+}
+
+// Defined in frameworks/base/core/java/android/bluetooth/BluetoothDevice.java
+enum TransportTypeEnum {
+ TRANSPORT_TYPE_AUTO = 0;
+ TRANSPORT_TYPE_BREDR = 1;
+ TRANSPORT_TYPE_LE = 2;
+}
+
+// Bond state enum
+// Defined in frameworks/base/core/java/android/bluetooth/BluetoothDevice.java
+enum BondStateEnum {
+ BOND_STATE_UNKNOWN = 0;
+ BOND_STATE_NONE = 10;
+ BOND_STATE_BONDING = 11;
+ BOND_STATE_BONDED = 12;
+}
+
+// Sub states within the bonding general state
+enum BondSubStateEnum {
+ BOND_SUB_STATE_UNKNOWN = 0;
+ BOND_SUB_STATE_LOCAL_OOB_DATA_PROVIDED = 1;
+ BOND_SUB_STATE_LOCAL_PIN_REQUESTED = 2;
+ BOND_SUB_STATE_LOCAL_PIN_REPLIED = 3;
+ BOND_SUB_STATE_LOCAL_SSP_REQUESTED = 4;
+ BOND_SUB_STATE_LOCAL_SSP_REPLIED = 5;
+}
+
+enum UnbondReasonEnum {
+ UNBOND_REASON_UNKNOWN = 0;
+ UNBOND_REASON_AUTH_FAILED = 1;
+ UNBOND_REASON_AUTH_REJECTED = 2;
+ UNBOND_REASON_AUTH_CANCELED = 3;
+ UNBOND_REASON_REMOTE_DEVICE_DOWN = 4;
+ UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5;
+ UNBOND_REASON_AUTH_TIMEOUT = 6;
+ UNBOND_REASON_REPEATED_ATTEMPTS = 7;
+ UNBOND_REASON_REMOTE_AUTH_CANCELED = 8;
+ UNBOND_REASON_REMOVED = 9;
+}
diff --git a/core/proto/android/bluetooth/hci/enums.proto b/core/proto/android/bluetooth/hci/enums.proto
index e1d96bb..ef894e5 100644
--- a/core/proto/android/bluetooth/hci/enums.proto
+++ b/core/proto/android/bluetooth/hci/enums.proto
@@ -351,7 +351,7 @@
EVT_COMMAND_COMPLETE = 0x0E;
EVT_COMMAND_STATUS = 0x0F;
EVT_HARDWARE_ERROR = 0x10;
- EVT_FLUSH_OCCURED = 0x11;
+ EVT_FLUSH_OCCURRED = 0x11;
EVT_ROLE_CHANGE = 0x12;
EVT_NUM_COMPL_DATA_PKTS = 0x13;
EVT_MODE_CHANGE = 0x14;
@@ -517,3 +517,43 @@
STATUS_CLB_DATA_TOO_BIG = 0x43;
STATUS_OPERATION_CANCELED_BY_HOST = 0x44; // Not currently used in system/bt
}
+
+enum BqrIdEnum {
+ BQR_ID_UNKNOWN = 0x00;
+ BQR_ID_MONITOR_MODE = 0x01;
+ BQR_ID_APPROACH_LSTO = 0x02;
+ BQR_ID_A2DP_AUDIO_CHOPPY = 0x03;
+ BQR_ID_SCO_VOICE_CHOPPY = 0x04;
+}
+
+enum BqrPacketTypeEnum {
+ BQR_PACKET_TYPE_UNKNOWN = 0x00;
+ BQR_PACKET_TYPE_ID = 0x01;
+ BQR_PACKET_TYPE_NULL = 0x02;
+ BQR_PACKET_TYPE_POLL = 0x03;
+ BQR_PACKET_TYPE_FHS = 0x04;
+ BQR_PACKET_TYPE_HV1 = 0x05;
+ BQR_PACKET_TYPE_HV2 = 0x06;
+ BQR_PACKET_TYPE_HV3 = 0x07;
+ BQR_PACKET_TYPE_DV = 0x08;
+ BQR_PACKET_TYPE_EV3 = 0x09;
+ BQR_PACKET_TYPE_EV4 = 0x0A;
+ BQR_PACKET_TYPE_EV5 = 0x0B;
+ BQR_PACKET_TYPE_2EV3 = 0x0C;
+ BQR_PACKET_TYPE_2EV5 = 0x0D;
+ BQR_PACKET_TYPE_3EV3 = 0x0E;
+ BQR_PACKET_TYPE_3EV5 = 0x0F;
+ BQR_PACKET_TYPE_DM1 = 0x10;
+ BQR_PACKET_TYPE_DH1 = 0x11;
+ BQR_PACKET_TYPE_DM3 = 0x12;
+ BQR_PACKET_TYPE_DH3 = 0x13;
+ BQR_PACKET_TYPE_DM5 = 0x14;
+ BQR_PACKET_TYPE_DH5 = 0x15;
+ BQR_PACKET_TYPE_AUX1 = 0x16;
+ BQR_PACKET_TYPE_2DH1 = 0x17;
+ BQR_PACKET_TYPE_2DH3 = 0x18;
+ BQR_PACKET_TYPE_2DH5 = 0x19;
+ BQR_PACKET_TYPE_3DH1 = 0x1A;
+ BQR_PACKET_TYPE_3DH3 = 0x1B;
+ BQR_PACKET_TYPE_3DH5 = 0x1C;
+}
diff --git a/core/proto/android/bluetooth/smp/enums.proto b/core/proto/android/bluetooth/smp/enums.proto
new file mode 100644
index 0000000..c6747b7
--- /dev/null
+++ b/core/proto/android/bluetooth/smp/enums.proto
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.bluetooth.smp;
+
+option java_outer_classname = "BluetoothSmpProtoEnums";
+option java_multiple_files = true;
+
+// SMP Pairing command codes
+enum CommandEnum {
+ CMD_UNKNOWN = 0x00;
+ CMD_PAIRING_REQUEST = 0x01;
+ CMD_PAIRING_RESPONSE = 0x02;
+ CMD_PAIRING_CONFIRM = 0x03;
+ CMD_PAIRING_RANDOM = 0x04;
+ CMD_PAIRING_FAILED = 0x05;
+ CMD_ENCRYPTION_INFON = 0x06;
+ CMD_MASTER_IDENTIFICATION = 0x07;
+ CMD_IDENTITY_INFO = 0x08;
+ CMD_IDENTITY_ADDR_INFO = 0x09;
+ CMD_SIGNING_INFO = 0x0A;
+ CMD_SECURITY_REQUEST = 0x0B;
+ CMD_PAIRING_PUBLIC_KEY = 0x0C;
+ CMD_PAIRING_DHKEY_CHECK = 0x0D;
+ CMD_PAIRING_KEYPRESS_INFO = 0x0E;
+}
+
+enum PairingFailReasonEnum {
+ PAIRING_FAIL_REASON_RESERVED = 0x00;
+ PAIRING_FAIL_REASON_PASSKEY_ENTRY = 0x01;
+ PAIRING_FAIL_REASON_OOB = 0x02;
+ PAIRING_FAIL_REASON_AUTH_REQ = 0x03;
+ PAIRING_FAIL_REASON_CONFIRM_VALUE = 0x04;
+ PAIRING_FAIL_REASON_PAIR_NOT_SUPPORT = 0x05;
+ PAIRING_FAIL_REASON_ENC_KEY_SIZE = 0x06;
+ PAIRING_FAIL_REASON_INVALID_CMD = 0x07;
+ PAIRING_FAIL_REASON_UNSPECIFIED = 0x08;
+ PAIRING_FAIL_REASON_REPEATED_ATTEMPTS = 0x09;
+ PAIRING_FAIL_REASON_INVALID_PARAMETERS = 0x0A;
+ PAIRING_FAIL_REASON_DHKEY_CHK = 0x0B;
+ PAIRING_FAIL_REASON_NUMERIC_COMPARISON = 0x0C;
+ PAIRING_FAIL_REASON_CLASSIC_PAIRING_IN_PROGR = 0x0D;
+ PAIRING_FAIL_REASON_XTRANS_DERIVE_NOT_ALLOW = 0x0E;
+}
\ No newline at end of file
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index 9b0d896..b0522f2 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,14 +26,15 @@
":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: [
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 dce8b61..96d1a28 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.util.FdEventsReader;
+import android.net.shared.FdEventsReader;
import android.os.Handler;
import android.system.Os;
@@ -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 f20e0163..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,26 +37,21 @@
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;
-import android.net.shared.NetdService;
import android.net.shared.ProvisioningConfiguration;
import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.ConditionVariable;
-import android.os.INetworkManagementService;
import android.os.Message;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.LocalLog;
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;
@@ -64,7 +60,7 @@
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.internal.util.WakeupMessage;
-import com.android.server.net.NetlinkTracker;
+import com.android.server.NetworkObserverRegistry;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -338,8 +334,9 @@
private final Dependencies mDependencies;
private final CountDownLatch mShutdownLatch;
private final ConnectivityManager mCm;
- private final INetworkManagementService mNwService;
- private final NetlinkTracker mNetlinkTracker;
+ private final INetd mNetd;
+ private final NetworkObserverRegistry mObserverRegistry;
+ private final IpClientLinkObserver mLinkObserver;
private final WakeupMessage mProvisioningTimeoutAlarm;
private final WakeupMessage mDhcpActionTimeoutAlarm;
private final SharedLog mLog;
@@ -373,15 +370,6 @@
private final ConditionVariable mApfDataSnapshotComplete = new ConditionVariable();
public static class Dependencies {
- public INetworkManagementService getNMS() {
- return INetworkManagementService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
- }
-
- public INetd getNetd() {
- return NetdService.getInstance();
- }
-
/**
* Get interface parameters for the specified interface.
*/
@@ -390,26 +378,14 @@
}
}
- public IpClient(Context context, String ifName, IIpClientCallbacks callback) {
- this(context, ifName, callback, new Dependencies());
- }
-
- /**
- * An expanded constructor, useful for dependency injection.
- * TODO: migrate all test users to mock IpClient directly and remove this ctor.
- */
public IpClient(Context context, String ifName, IIpClientCallbacks callback,
- INetworkManagementService nwService) {
- this(context, ifName, callback, new Dependencies() {
- @Override
- public INetworkManagementService getNMS() {
- return nwService;
- }
- });
+ NetworkObserverRegistry observerRegistry) {
+ this(context, ifName, callback, observerRegistry, new Dependencies());
}
@VisibleForTesting
- IpClient(Context context, String ifName, IIpClientCallbacks callback, Dependencies deps) {
+ IpClient(Context context, String ifName, IIpClientCallbacks callback,
+ NetworkObserverRegistry observerRegistry, Dependencies deps) {
super(IpClient.class.getSimpleName() + "." + ifName);
Preconditions.checkNotNull(ifName);
Preconditions.checkNotNull(callback);
@@ -422,7 +398,7 @@
mDependencies = deps;
mShutdownLatch = new CountDownLatch(1);
mCm = mContext.getSystemService(ConnectivityManager.class);
- mNwService = deps.getNMS();
+ mObserverRegistry = observerRegistry;
sSmLogs.putIfAbsent(mInterfaceName, new SharedLog(MAX_LOG_RECORDS, mTag));
mLog = sSmLogs.get(mInterfaceName);
@@ -433,19 +409,15 @@
// TODO: Consider creating, constructing, and passing in some kind of
// InterfaceController.Dependencies class.
- mInterfaceCtrl = new InterfaceController(mInterfaceName, deps.getNetd(), mLog);
+ mNetd = mContext.getSystemService(INetd.class);
+ mInterfaceCtrl = new InterfaceController(mInterfaceName, mNetd, mLog);
- mNetlinkTracker = new NetlinkTracker(
+ mLinkObserver = new IpClientLinkObserver(
mInterfaceName,
- new NetlinkTracker.Callback() {
- @Override
- public void update() {
- sendMessage(EVENT_NETLINK_LINKPROPERTIES_CHANGED);
- }
- }) {
+ () -> sendMessage(EVENT_NETLINK_LINKPROPERTIES_CHANGED)) {
@Override
- public void interfaceAdded(String iface) {
- super.interfaceAdded(iface);
+ public void onInterfaceAdded(String iface) {
+ super.onInterfaceAdded(iface);
if (mClatInterfaceName.equals(iface)) {
mCallback.setNeighborDiscoveryOffload(false);
} else if (!mInterfaceName.equals(iface)) {
@@ -457,8 +429,8 @@
}
@Override
- public void interfaceRemoved(String iface) {
- super.interfaceRemoved(iface);
+ public void onInterfaceRemoved(String iface) {
+ super.onInterfaceRemoved(iface);
// TODO: Also observe mInterfaceName going down and take some
// kind of appropriate action.
if (mClatInterfaceName.equals(iface)) {
@@ -570,19 +542,11 @@
}
private void startStateMachineUpdaters() {
- try {
- mNwService.registerObserver(mNetlinkTracker);
- } catch (RemoteException e) {
- logError("Couldn't register NetlinkTracker: %s", e);
- }
+ mObserverRegistry.registerObserverForNonblockingCallback(mLinkObserver);
}
private void stopStateMachineUpdaters() {
- try {
- mNwService.unregisterObserver(mNetlinkTracker);
- } catch (RemoteException e) {
- logError("Couldn't unregister NetlinkTracker: %s", e);
- }
+ mObserverRegistry.unregisterObserver(mLinkObserver);
}
@Override
@@ -805,7 +769,7 @@
// we should only call this if we know for sure that there are no IP addresses
// assigned to the interface, etc.
private void resetLinkProperties() {
- mNetlinkTracker.clearLinkProperties();
+ mLinkObserver.clearLinkProperties();
mConfiguration = null;
mDhcpResults = null;
mTcpBufferSizes = "";
@@ -984,10 +948,10 @@
// - IPv6 DNS servers
//
// N.B.: this is fundamentally race-prone and should be fixed by
- // changing NetlinkTracker from a hybrid edge/level model to an
+ // changing IpClientLinkObserver from a hybrid edge/level model to an
// edge-only model, or by giving IpClient its own netlink socket(s)
// so as to track all required information directly.
- LinkProperties netlinkLinkProperties = mNetlinkTracker.getLinkProperties();
+ LinkProperties netlinkLinkProperties = mLinkObserver.getLinkProperties();
newLp.setLinkAddresses(netlinkLinkProperties.getLinkAddresses());
for (RouteInfo route : netlinkLinkProperties.getRoutes()) {
newLp.addRoute(route);
@@ -1027,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);
@@ -1128,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;
@@ -1166,8 +1130,7 @@
// necessary or does reading from settings at startup suffice?).
final int numSolicits = 5;
final int interSolicitIntervalMs = 750;
- setNeighborParameters(mDependencies.getNetd(), mInterfaceName,
- numSolicits, interSolicitIntervalMs);
+ setNeighborParameters(mNetd, mInterfaceName, numSolicits, interSolicitIntervalMs);
} catch (Exception e) {
mLog.e("Failed to adjust neighbor parameters", e);
// Carry on using the system defaults (currently: 3, 1000);
@@ -1384,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/IpClientLinkObserver.java b/packages/NetworkStack/src/android/net/ip/IpClientLinkObserver.java
new file mode 100644
index 0000000..8ad99aa0
--- /dev/null
+++ b/packages/NetworkStack/src/android/net/ip/IpClientLinkObserver.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.ip;
+
+import android.net.InetAddresses;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.RouteInfo;
+import android.util.Log;
+
+import com.android.server.NetworkObserver;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Keeps track of link configuration received from Netd.
+ *
+ * An instance of this class is constructed by passing in an interface name and a callback. The
+ * owner is then responsible for registering the tracker with NetworkObserverRegistry. When the
+ * class receives update notifications, it applies the update to its local LinkProperties, and if
+ * something has changed, notifies its owner of the update via the callback.
+ *
+ * The owner can then call {@code getLinkProperties()} in order to find out
+ * what changed. If in the meantime the LinkProperties stored here have changed,
+ * this class will return the current LinkProperties. Because each change
+ * triggers an update callback after the change is made, the owner may get more
+ * callbacks than strictly necessary (some of which may be no-ops), but will not
+ * be out of sync once all callbacks have been processed.
+ *
+ * Threading model:
+ *
+ * - The owner of this class is expected to create it, register it, and call
+ * getLinkProperties or clearLinkProperties on its thread.
+ * - Most of the methods in the class are implementing NetworkObserver and are called
+ * on the handler used to register the observer.
+ * - All accesses to mLinkProperties must be synchronized(this). All the other
+ * member variables are immutable once the object is constructed.
+ *
+ * @hide
+ */
+public class IpClientLinkObserver implements NetworkObserver {
+ private final String mTag;
+
+ /**
+ * Callback used by {@link IpClientLinkObserver} to send update notifications.
+ */
+ public interface Callback {
+ /**
+ * Called when some properties of the link were updated.
+ */
+ void update();
+ }
+
+ private final String mInterfaceName;
+ private final Callback mCallback;
+ private final LinkProperties mLinkProperties;
+ private DnsServerRepository mDnsServerRepository;
+
+ private static final boolean DBG = false;
+
+ public IpClientLinkObserver(String iface, Callback callback) {
+ mTag = "NetlinkTracker/" + iface;
+ mInterfaceName = iface;
+ mCallback = callback;
+ mLinkProperties = new LinkProperties();
+ mLinkProperties.setInterfaceName(mInterfaceName);
+ mDnsServerRepository = new DnsServerRepository();
+ }
+
+ private void maybeLog(String operation, String iface, LinkAddress address) {
+ if (DBG) {
+ Log.d(mTag, operation + ": " + address + " on " + iface
+ + " flags " + address.getFlags() + " scope " + address.getScope());
+ }
+ }
+
+ private void maybeLog(String operation, Object o) {
+ if (DBG) {
+ Log.d(mTag, operation + ": " + o.toString());
+ }
+ }
+
+ @Override
+ public void onInterfaceRemoved(String iface) {
+ maybeLog("interfaceRemoved", iface);
+ if (mInterfaceName.equals(iface)) {
+ // Our interface was removed. Clear our LinkProperties and tell our owner that they are
+ // now empty. Note that from the moment that the interface is removed, any further
+ // interface-specific messages (e.g., RTM_DELADDR) will not reach us, because the netd
+ // code that parses them will not be able to resolve the ifindex to an interface name.
+ clearLinkProperties();
+ mCallback.update();
+ }
+ }
+
+ @Override
+ public void onInterfaceAddressUpdated(LinkAddress address, String iface) {
+ if (mInterfaceName.equals(iface)) {
+ maybeLog("addressUpdated", iface, address);
+ boolean changed;
+ synchronized (this) {
+ changed = mLinkProperties.addLinkAddress(address);
+ }
+ if (changed) {
+ mCallback.update();
+ }
+ }
+ }
+
+ @Override
+ public void onInterfaceAddressRemoved(LinkAddress address, String iface) {
+ if (mInterfaceName.equals(iface)) {
+ maybeLog("addressRemoved", iface, address);
+ boolean changed;
+ synchronized (this) {
+ changed = mLinkProperties.removeLinkAddress(address);
+ }
+ if (changed) {
+ mCallback.update();
+ }
+ }
+ }
+
+ @Override
+ public void onRouteUpdated(RouteInfo route) {
+ if (mInterfaceName.equals(route.getInterface())) {
+ maybeLog("routeUpdated", route);
+ boolean changed;
+ synchronized (this) {
+ changed = mLinkProperties.addRoute(route);
+ }
+ if (changed) {
+ mCallback.update();
+ }
+ }
+ }
+
+ @Override
+ public void onRouteRemoved(RouteInfo route) {
+ if (mInterfaceName.equals(route.getInterface())) {
+ maybeLog("routeRemoved", route);
+ boolean changed;
+ synchronized (this) {
+ changed = mLinkProperties.removeRoute(route);
+ }
+ if (changed) {
+ mCallback.update();
+ }
+ }
+ }
+
+ @Override
+ public void onInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
+ if (mInterfaceName.equals(iface)) {
+ maybeLog("interfaceDnsServerInfo", Arrays.toString(addresses));
+ boolean changed = mDnsServerRepository.addServers(lifetime, addresses);
+ if (changed) {
+ synchronized (this) {
+ mDnsServerRepository.setDnsServersOn(mLinkProperties);
+ }
+ mCallback.update();
+ }
+ }
+ }
+
+ /**
+ * Returns a copy of this object's LinkProperties.
+ */
+ public synchronized LinkProperties getLinkProperties() {
+ return new LinkProperties(mLinkProperties);
+ }
+
+ /**
+ * Reset this object's LinkProperties.
+ */
+ public synchronized void clearLinkProperties() {
+ // Clear the repository before clearing mLinkProperties. That way, if a clear() happens
+ // while interfaceDnsServerInfo() is being called, we'll end up with no DNS servers in
+ // mLinkProperties, as desired.
+ mDnsServerRepository = new DnsServerRepository();
+ mLinkProperties.clear();
+ mLinkProperties.setInterfaceName(mInterfaceName);
+ }
+
+ /**
+ * Tracks DNS server updates received from Netlink.
+ *
+ * The network may announce an arbitrary number of DNS servers in Router Advertisements at any
+ * time. Each announcement has a lifetime; when the lifetime expires, the servers should not be
+ * used any more. In this way, the network can gracefully migrate clients from one set of DNS
+ * servers to another. Announcements can both raise and lower the lifetime, and an announcement
+ * can expire servers by announcing them with a lifetime of zero.
+ *
+ * Typically the system will only use a small number (2 or 3; {@code NUM_CURRENT_SERVERS}) of
+ * DNS servers at any given time. These are referred to as the current servers. In case all the
+ * current servers expire, the class also keeps track of a larger (but limited) number of
+ * servers that are promoted to current servers when the current ones expire. In order to
+ * minimize updates to the rest of the system (and potentially expensive cache flushes) this
+ * class attempts to keep the list of current servers constant where possible. More
+ * specifically, the list of current servers is only updated if a new server is learned and
+ * there are not yet {@code NUM_CURRENT_SERVERS} current servers, or if one or more of the
+ * current servers expires or is pushed out of the set. Therefore, the current servers will not
+ * necessarily be the ones with the highest lifetime, but the ones learned first.
+ *
+ * This is by design: if instead the class always preferred the servers with the highest
+ * lifetime, a (misconfigured?) network where two or more routers announce more than
+ * {@code NUM_CURRENT_SERVERS} unique servers would cause persistent oscillations.
+ *
+ * TODO: Currently servers are only expired when a new DNS update is received.
+ * Update them using timers, or possibly on every notification received by NetlinkTracker.
+ *
+ * Threading model: run by NetlinkTracker. Methods are synchronized(this) just in case netlink
+ * notifications are sent by multiple threads. If future threads use alarms to expire, those
+ * alarms must also be synchronized(this).
+ *
+ */
+ private static class DnsServerRepository {
+
+ /** How many DNS servers we will use. 3 is suggested by RFC 6106. */
+ static final int NUM_CURRENT_SERVERS = 3;
+
+ /** How many DNS servers we'll keep track of, in total. */
+ static final int NUM_SERVERS = 12;
+
+ /** Stores up to {@code NUM_CURRENT_SERVERS} DNS servers we're currently using. */
+ private Set<InetAddress> mCurrentServers;
+
+ public static final String TAG = "DnsServerRepository";
+
+ /**
+ * Stores all the DNS servers we know about, for use when the current servers expire.
+ * Always sorted in order of decreasing expiry. The elements in this list are also the
+ * values of mIndex, and may be elements in mCurrentServers.
+ */
+ private ArrayList<DnsServerEntry> mAllServers;
+
+ /**
+ * Indexes the servers so we can update their lifetimes more quickly in the common case
+ * where servers are not being added, but only being refreshed.
+ */
+ private HashMap<InetAddress, DnsServerEntry> mIndex;
+
+ DnsServerRepository() {
+ mCurrentServers = new HashSet<>();
+ mAllServers = new ArrayList<>(NUM_SERVERS);
+ mIndex = new HashMap<>(NUM_SERVERS);
+ }
+
+ /** Sets the DNS servers of the provided LinkProperties object to the current servers. */
+ public synchronized void setDnsServersOn(LinkProperties lp) {
+ lp.setDnsServers(mCurrentServers);
+ }
+
+ /**
+ * Notifies the class of new DNS server information.
+ * @param lifetime the time in seconds that the DNS servers are valid.
+ * @param addresses the string representations of the IP addresses of DNS servers to use.
+ */
+ public synchronized boolean addServers(long lifetime, String[] addresses) {
+ // The lifetime is actually an unsigned 32-bit number, but Java doesn't have unsigned.
+ // Technically 0xffffffff (the maximum) is special and means "forever", but 2^32 seconds
+ // (136 years) is close enough.
+ long now = System.currentTimeMillis();
+ long expiry = now + 1000 * lifetime;
+
+ // Go through the list of servers. For each one, update the entry if one exists, and
+ // create one if it doesn't.
+ for (String addressString : addresses) {
+ InetAddress address;
+ try {
+ address = InetAddresses.parseNumericAddress(addressString);
+ } catch (IllegalArgumentException ex) {
+ continue;
+ }
+
+ if (!updateExistingEntry(address, expiry)) {
+ // There was no entry for this server. Create one, unless it's already expired
+ // (i.e., if the lifetime is zero; it cannot be < 0 because it's unsigned).
+ if (expiry > now) {
+ DnsServerEntry entry = new DnsServerEntry(address, expiry);
+ mAllServers.add(entry);
+ mIndex.put(address, entry);
+ }
+ }
+ }
+
+ // Sort the servers by expiry.
+ Collections.sort(mAllServers);
+
+ // Prune excess entries and update the current server list.
+ return updateCurrentServers();
+ }
+
+ private synchronized boolean updateExistingEntry(InetAddress address, long expiry) {
+ DnsServerEntry existing = mIndex.get(address);
+ if (existing != null) {
+ existing.expiry = expiry;
+ return true;
+ }
+ return false;
+ }
+
+ private synchronized boolean updateCurrentServers() {
+ long now = System.currentTimeMillis();
+ boolean changed = false;
+
+ // Prune excess or expired entries.
+ for (int i = mAllServers.size() - 1; i >= 0; i--) {
+ if (i >= NUM_SERVERS || mAllServers.get(i).expiry < now) {
+ DnsServerEntry removed = mAllServers.remove(i);
+ mIndex.remove(removed.address);
+ changed |= mCurrentServers.remove(removed.address);
+ } else {
+ break;
+ }
+ }
+
+ // Add servers to the current set, in order of decreasing lifetime, until it has enough.
+ // Prefer existing servers over new servers in order to minimize updates to the rest of
+ // the system and avoid persistent oscillations.
+ for (DnsServerEntry entry : mAllServers) {
+ if (mCurrentServers.size() < NUM_CURRENT_SERVERS) {
+ changed |= mCurrentServers.add(entry.address);
+ } else {
+ break;
+ }
+ }
+ return changed;
+ }
+ }
+
+ /**
+ * Represents a DNS server entry with an expiry time.
+ *
+ * Implements Comparable so DNS server entries can be sorted by lifetime, longest-lived first.
+ * The ordering of entries with the same lifetime is unspecified, because given two servers with
+ * identical lifetimes, we don't care which one we use, and only comparing the lifetime is much
+ * faster than comparing the IP address as well.
+ *
+ * Note: this class has a natural ordering that is inconsistent with equals.
+ */
+ private static class DnsServerEntry implements Comparable<DnsServerEntry> {
+ /** The IP address of the DNS server. */
+ public final InetAddress address;
+ /** The time until which the DNS server may be used. A Java millisecond time as might be
+ * returned by currentTimeMillis(). */
+ public long expiry;
+
+ DnsServerEntry(InetAddress address, long expiry) throws IllegalArgumentException {
+ this.address = address;
+ this.expiry = expiry;
+ }
+
+ public int compareTo(DnsServerEntry other) {
+ return Long.compare(other.expiry, this.expiry);
+ }
+ }
+}
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/android/net/util/PacketReader.java b/packages/NetworkStack/src/android/net/util/PacketReader.java
index 4aec6b6..94b1e9f 100644
--- a/packages/NetworkStack/src/android/net/util/PacketReader.java
+++ b/packages/NetworkStack/src/android/net/util/PacketReader.java
@@ -18,6 +18,7 @@
import static java.lang.Math.max;
+import android.net.shared.FdEventsReader;
import android.os.Handler;
import android.system.Os;
diff --git a/packages/NetworkStack/src/com/android/server/NetworkObserver.java b/packages/NetworkStack/src/com/android/server/NetworkObserver.java
index d3b40a6..cccec0b 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkObserver.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkObserver.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.net.LinkAddress;
+import android.net.RouteInfo;
/**
* Observer for network events, to use with {@link NetworkObserverRegistry}.
@@ -77,11 +78,11 @@
* @see android.net.INetdUnsolicitedEventListener
* #onRouteChanged(boolean, String, String, String)
*/
- default void onRouteUpdated(String route, String gateway, String ifName) {}
+ default void onRouteUpdated(RouteInfo route) {}
/**
* @see android.net.INetdUnsolicitedEventListener
* #onRouteChanged(boolean, String, String, String)
*/
- default void onRouteRemoved(String route, String gateway, String ifName) {}
+ default void onRouteRemoved(RouteInfo route) {}
}
diff --git a/packages/NetworkStack/src/com/android/server/NetworkObserverRegistry.java b/packages/NetworkStack/src/com/android/server/NetworkObserverRegistry.java
index 14e6c5f..6fb4b0d 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkObserverRegistry.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkObserverRegistry.java
@@ -15,14 +15,21 @@
*/
package com.android.server;
+import static android.net.RouteInfo.RTN_UNICAST;
+
import android.annotation.NonNull;
import android.net.INetd;
import android.net.INetdUnsolicitedEventListener;
+import android.net.InetAddresses;
+import android.net.IpPrefix;
import android.net.LinkAddress;
+import android.net.RouteInfo;
import android.os.Handler;
import android.os.RemoteException;
+import android.util.Log;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -32,6 +39,7 @@
* all INetworkManagementEventObserver objects that have registered with it.
*/
public class NetworkObserverRegistry extends INetdUnsolicitedEventListener.Stub {
+ private static final String TAG = NetworkObserverRegistry.class.getSimpleName();
/**
* Constructs a new NetworkObserverRegistry.
@@ -50,7 +58,7 @@
netd.registerUnsolicitedEventListener(this);
}
- private final ConcurrentHashMap<NetworkObserver, Handler> mObservers =
+ private final ConcurrentHashMap<NetworkObserver, Optional<Handler>> mObservers =
new ConcurrentHashMap<>();
/**
@@ -58,7 +66,20 @@
* This method may be called on any thread.
*/
public void registerObserver(@NonNull NetworkObserver observer, @NonNull Handler handler) {
- mObservers.put(observer, handler);
+ if (handler == null) {
+ throw new IllegalArgumentException("handler must be non-null");
+ }
+ mObservers.put(observer, Optional.of(handler));
+ }
+
+ /**
+ * Registers the specified observer, and start sending callbacks to it.
+ *
+ * <p>This method must only be called with callbacks that are nonblocking, such as callbacks
+ * that only send a message to a StateMachine.
+ */
+ public void registerObserverForNonblockingCallback(@NonNull NetworkObserver observer) {
+ mObservers.put(observer, Optional.empty());
}
/**
@@ -77,9 +98,19 @@
private void invokeForAllObservers(@NonNull final NetworkObserverEventCallback callback) {
// ConcurrentHashMap#entrySet is weakly consistent: observers that were in the map before
// creation will be processed, those added during traversal may or may not.
- for (Map.Entry<NetworkObserver, Handler> entry : mObservers.entrySet()) {
+ for (Map.Entry<NetworkObserver, Optional<Handler>> entry : mObservers.entrySet()) {
final NetworkObserver observer = entry.getKey();
- entry.getValue().post(() -> callback.sendCallback(observer));
+ final Optional<Handler> handler = entry.getValue();
+ if (handler.isPresent()) {
+ handler.get().post(() -> callback.sendCallback(observer));
+ return;
+ }
+
+ try {
+ callback.sendCallback(observer);
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Error sending callback to observer", e);
+ }
}
}
@@ -138,10 +169,13 @@
@Override
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, RTN_UNICAST);
if (updated) {
- invokeForAllObservers(o -> o.onRouteUpdated(route, gateway, ifName));
+ invokeForAllObservers(o -> o.onRouteUpdated(processRoute));
} else {
- invokeForAllObservers(o -> o.onRouteRemoved(route, gateway, ifName));
+ invokeForAllObservers(o -> o.onRouteRemoved(processRoute));
}
}
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index 631ee45..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;
@@ -117,7 +118,11 @@
mObserverRegistry = new NetworkObserverRegistry();
mCm = context.getSystemService(ConnectivityManager.class);
- // TODO: call mObserverRegistry here after adding sepolicy changes
+ try {
+ mObserverRegistry.register(mNetd);
+ } catch (RemoteException e) {
+ mLog.e("Error registering observer on Netd", e);
+ }
}
@NonNull
@@ -146,19 +151,18 @@
}
@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));
}
@Override
public void makeIpClient(String ifName, IIpClientCallbacks cb) throws RemoteException {
- final IpClient ipClient = new IpClient(mContext, ifName, cb);
+ final IpClient ipClient = new IpClient(mContext, ifName, cb, mObserverRegistry);
synchronized (mIpClients) {
final Iterator<WeakReference<IpClient>> it = mIpClients.iterator();
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index 96eaa50..f21561f 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;
@@ -310,14 +309,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 +368,7 @@
// we can ever fetch them.
// TODO: Delete ASAP.
mLinkProperties = new LinkProperties();
- mNetworkCapabilities = new NetworkCapabilities();
- mNetworkCapabilities.clearAll();
+ mNetworkCapabilities = new NetworkCapabilities(null);
}
/**
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
index 4ae044de..7e57d1e 100644
--- a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
+++ b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
@@ -46,7 +46,6 @@
import android.net.shared.InitialConfiguration;
import android.net.shared.ProvisioningConfiguration;
import android.net.util.InterfaceParams;
-import android.os.INetworkManagementService;
import android.provider.Settings;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -54,7 +53,8 @@
import com.android.internal.R;
import com.android.internal.util.test.FakeSettingsProvider;
-import com.android.server.net.BaseNetworkObserver;
+import com.android.server.NetworkObserver;
+import com.android.server.NetworkObserverRegistry;
import org.junit.Before;
import org.junit.Test;
@@ -87,15 +87,15 @@
@Mock private Context mContext;
@Mock private ConnectivityManager mCm;
- @Mock private INetworkManagementService mNMService;
+ @Mock private NetworkObserverRegistry mObserverRegistry;
@Mock private INetd mNetd;
@Mock private Resources mResources;
@Mock private IIpClientCallbacks mCb;
@Mock private AlarmManager mAlarm;
- @Mock private IpClient.Dependencies mDependecies;
+ @Mock private IpClient.Dependencies mDependencies;
private MockContentResolver mContentResolver;
- private BaseNetworkObserver mObserver;
+ private NetworkObserver mObserver;
private InterfaceParams mIfParams;
@Before
@@ -104,6 +104,7 @@
when(mContext.getSystemService(eq(Context.ALARM_SERVICE))).thenReturn(mAlarm);
when(mContext.getSystemService(eq(ConnectivityManager.class))).thenReturn(mCm);
+ when(mContext.getSystemService(INetd.class)).thenReturn(mNetd);
when(mContext.getResources()).thenReturn(mResources);
when(mResources.getInteger(R.integer.config_networkAvoidBadWifi))
.thenReturn(DEFAULT_AVOIDBADWIFI_CONFIG_VALUE);
@@ -113,28 +114,24 @@
when(mContext.getContentResolver()).thenReturn(mContentResolver);
mIfParams = null;
-
- when(mDependecies.getNMS()).thenReturn(mNMService);
- when(mDependecies.getNetd()).thenReturn(mNetd);
}
private void setTestInterfaceParams(String ifname) {
mIfParams = (ifname != null)
? new InterfaceParams(ifname, TEST_IFINDEX, TEST_MAC)
: null;
- when(mDependecies.getInterfaceParams(anyString())).thenReturn(mIfParams);
+ when(mDependencies.getInterfaceParams(anyString())).thenReturn(mIfParams);
}
private IpClient makeIpClient(String ifname) throws Exception {
setTestInterfaceParams(ifname);
- final IpClient ipc = new IpClient(mContext, ifname, mCb, mDependecies);
+ final IpClient ipc = new IpClient(mContext, ifname, mCb, mObserverRegistry, mDependencies);
verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(ifname, false);
verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(ifname);
- ArgumentCaptor<BaseNetworkObserver> arg =
- ArgumentCaptor.forClass(BaseNetworkObserver.class);
- verify(mNMService, times(1)).registerObserver(arg.capture());
+ ArgumentCaptor<NetworkObserver> arg = ArgumentCaptor.forClass(NetworkObserver.class);
+ verify(mObserverRegistry, times(1)).registerObserverForNonblockingCallback(arg.capture());
mObserver = arg.getValue();
- reset(mNMService);
+ reset(mObserverRegistry);
reset(mNetd);
// Verify IpClient doesn't call onLinkPropertiesChange() when it starts.
verify(mCb, never()).onLinkPropertiesChange(any());
@@ -152,7 +149,8 @@
public void testNullInterfaceNameMostDefinitelyThrows() throws Exception {
setTestInterfaceParams(null);
try {
- final IpClient ipc = new IpClient(mContext, null, mCb, mDependecies);
+ final IpClient ipc = new IpClient(
+ mContext, null, mCb, mObserverRegistry, mDependencies);
ipc.shutdown();
fail();
} catch (NullPointerException npe) {
@@ -165,7 +163,8 @@
final String ifname = "lo";
setTestInterfaceParams(ifname);
try {
- final IpClient ipc = new IpClient(mContext, ifname, null, mDependecies);
+ final IpClient ipc = new IpClient(
+ mContext, ifname, null, mObserverRegistry, mDependencies);
ipc.shutdown();
fail();
} catch (NullPointerException npe) {
@@ -176,14 +175,16 @@
@Test
public void testInvalidInterfaceDoesNotThrow() throws Exception {
setTestInterfaceParams(TEST_IFNAME);
- final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mDependecies);
+ final IpClient ipc = new IpClient(
+ mContext, TEST_IFNAME, mCb, mObserverRegistry, mDependencies);
ipc.shutdown();
}
@Test
public void testInterfaceNotFoundFailsImmediately() throws Exception {
setTestInterfaceParams(null);
- final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mDependecies);
+ final IpClient ipc = new IpClient(
+ mContext, TEST_IFNAME, mCb, mObserverRegistry, mDependencies);
ipc.startProvisioning(new ProvisioningConfiguration());
verify(mCb, times(1)).onProvisioningFailure(any());
ipc.shutdown();
@@ -247,13 +248,13 @@
// Add N - 1 addresses
for (int i = 0; i < lastAddr; i++) {
- mObserver.addressUpdated(iface, new LinkAddress(addresses[i]));
+ mObserver.onInterfaceAddressUpdated(new LinkAddress(addresses[i]), iface);
verify(mCb, timeout(TEST_TIMEOUT_MS)).onLinkPropertiesChange(any());
reset(mCb);
}
// Add Nth address
- mObserver.addressUpdated(iface, new LinkAddress(addresses[lastAddr]));
+ mObserver.onInterfaceAddressUpdated(new LinkAddress(addresses[lastAddr]), iface);
LinkProperties want = linkproperties(links(addresses), routes(prefixes));
want.setInterfaceName(iface);
verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).onProvisioningSuccess(argThat(
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/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 1519c17..c8e5d2b 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;
@@ -5012,8 +5013,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/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 2f66fd7..da4df22 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -47,8 +47,10 @@
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.INetd;
+import android.net.INetdUnsolicitedEventListener;
import android.net.INetworkManagementEventObserver;
import android.net.ITetheringStatsProvider;
+import android.net.InetAddresses;
import android.net.InterfaceConfiguration;
import android.net.InterfaceConfigurationParcel;
import android.net.IpPrefix;
@@ -60,8 +62,7 @@
import android.net.RouteInfo;
import android.net.TetherStatsParcel;
import android.net.UidRange;
-import android.net.shared.NetdService;
-import android.net.shared.NetworkObserverRegistry;
+import android.net.util.NetdService;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Handler;
@@ -205,13 +206,16 @@
private INetd mNetdService;
- private NMSNetworkObserverRegistry mNetworkObserverRegistry;
+ private final NetdUnsolicitedEventListener mNetdUnsolicitedEventListener;
private IBatteryStats mBatteryStats;
private final Thread mThread;
private CountDownLatch mConnectedSignal = new CountDownLatch(1);
+ private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
+ new RemoteCallbackList<>();
+
private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
@GuardedBy("mTetheringStatsProviders")
@@ -321,6 +325,8 @@
mDaemonHandler = new Handler(FgThread.get().getLooper());
+ mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
+
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
@@ -339,7 +345,7 @@
mFgHandler = null;
mThread = null;
mServices = null;
- mNetworkObserverRegistry = null;
+ mNetdUnsolicitedEventListener = null;
}
static NetworkManagementService create(Context context, String socket, SystemServices services)
@@ -387,12 +393,14 @@
@Override
public void registerObserver(INetworkManagementEventObserver observer) {
- mNetworkObserverRegistry.registerObserver(observer);
+ mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+ mObservers.register(observer);
}
@Override
public void unregisterObserver(INetworkManagementEventObserver observer) {
- mNetworkObserverRegistry.unregisterObserver(observer);
+ mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+ mObservers.unregister(observer);
}
@FunctionalInterface
@@ -400,97 +408,123 @@
public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
}
- private class NMSNetworkObserverRegistry extends NetworkObserverRegistry {
- NMSNetworkObserverRegistry(Context context, Handler handler, INetd netd)
- throws RemoteException {
- super(context, handler, netd);
+ private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
+ final int length = mObservers.beginBroadcast();
+ try {
+ for (int i = 0; i < length; i++) {
+ try {
+ eventCallback.sendCallback(mObservers.getBroadcastItem(i));
+ } catch (RemoteException | RuntimeException e) {
+ }
+ }
+ } finally {
+ mObservers.finishBroadcast();
}
+ }
- /**
- * Notify our observers of a change in the data activity state of the interface
- */
- @Override
- public void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos,
- int uid, boolean fromRadio) {
- final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
- int powerState = isActive
- ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
- : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
+ /**
+ * Notify our observers of an interface status change
+ */
+ private void notifyInterfaceStatusChanged(String iface, boolean up) {
+ invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
+ }
- if (isMobile) {
- if (!fromRadio) {
- if (mMobileActivityFromRadio) {
- // If this call is not coming from a report from the radio itself, but we
- // have previously received reports from the radio, then we will take the
- // power state to just be whatever the radio last reported.
- powerState = mLastPowerStateFromRadio;
- }
- } else {
- mMobileActivityFromRadio = true;
+ /**
+ * Notify our observers of an interface link state change
+ * (typically, an Ethernet cable has been plugged-in or unplugged).
+ */
+ private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
+ invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
+ }
+
+ /**
+ * Notify our observers of an interface addition.
+ */
+ private void notifyInterfaceAdded(String iface) {
+ invokeForAllObservers(o -> o.interfaceAdded(iface));
+ }
+
+ /**
+ * Notify our observers of an interface removal.
+ */
+ private void notifyInterfaceRemoved(String iface) {
+ // netd already clears out quota and alerts for removed ifaces; update
+ // our sanity-checking state.
+ mActiveAlerts.remove(iface);
+ mActiveQuotas.remove(iface);
+ invokeForAllObservers(o -> o.interfaceRemoved(iface));
+ }
+
+ /**
+ * Notify our observers of a limit reached.
+ */
+ private void notifyLimitReached(String limitName, String iface) {
+ invokeForAllObservers(o -> o.limitReached(limitName, iface));
+ }
+
+ /**
+ * Notify our observers of a change in the data activity state of the interface
+ */
+ private void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos,
+ int uid, boolean fromRadio) {
+ final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
+ int powerState = isActive
+ ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
+ : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
+ if (isMobile) {
+ if (!fromRadio) {
+ if (mMobileActivityFromRadio) {
+ // If this call is not coming from a report from the radio itself, but we
+ // have previously received reports from the radio, then we will take the
+ // power state to just be whatever the radio last reported.
+ powerState = mLastPowerStateFromRadio;
}
- if (mLastPowerStateFromRadio != powerState) {
- mLastPowerStateFromRadio = powerState;
- try {
- getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
- } catch (RemoteException e) {
- }
- }
+ } else {
+ mMobileActivityFromRadio = true;
}
-
- if (ConnectivityManager.isNetworkTypeWifi(type)) {
- if (mLastPowerStateFromWifi != powerState) {
- mLastPowerStateFromWifi = powerState;
- try {
- getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
- } catch (RemoteException e) {
- }
+ if (mLastPowerStateFromRadio != powerState) {
+ mLastPowerStateFromRadio = powerState;
+ try {
+ getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
+ } catch (RemoteException e) {
}
}
-
- if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
- // Report the change in data activity. We don't do this if this is a change
- // on the mobile network, that is not coming from the radio itself, and we
- // have previously seen change reports from the radio. In that case only
- // the radio is the authority for the current state.
- final boolean active = isActive;
- super.notifyInterfaceClassActivity(type, isActive, tsNanos, uid, fromRadio);
- }
-
- boolean report = false;
- synchronized (mIdleTimerLock) {
- if (mActiveIdleTimers.isEmpty()) {
- // If there are no idle timers, we are not monitoring activity, so we
- // are always considered active.
- isActive = true;
- }
- if (mNetworkActive != isActive) {
- mNetworkActive = isActive;
- report = isActive;
- }
- }
- if (report) {
- reportNetworkActive();
- }
}
- /**
- * Notify our observers of an interface removal.
- */
- @Override
- public void notifyInterfaceRemoved(String iface) {
- // netd already clears out quota and alerts for removed ifaces; update
- // our sanity-checking state.
- mActiveAlerts.remove(iface);
- mActiveQuotas.remove(iface);
- super.notifyInterfaceRemoved(iface);
+ if (ConnectivityManager.isNetworkTypeWifi(type)) {
+ if (mLastPowerStateFromWifi != powerState) {
+ mLastPowerStateFromWifi = powerState;
+ try {
+ getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
+ } catch (RemoteException e) {
+ }
+ }
}
- @Override
- public void onStrictCleartextDetected(int uid, String hex) throws RemoteException {
- // Don't need to post to mDaemonHandler because the only thing
- // that notifyCleartextNetwork does is post to a handler
- ActivityManager.getService().notifyCleartextNetwork(uid,
- HexDump.hexStringToByteArray(hex));
+ if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
+ // Report the change in data activity. We don't do this if this is a change
+ // on the mobile network, that is not coming from the radio itself, and we
+ // have previously seen change reports from the radio. In that case only
+ // the radio is the authority for the current state.
+ final boolean active = isActive;
+ invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
+ Integer.toString(type), active, tsNanos));
+ }
+
+ boolean report = false;
+ synchronized (mIdleTimerLock) {
+ if (mActiveIdleTimers.isEmpty()) {
+ // If there are no idle timers, we are not monitoring activity, so we
+ // are always considered active.
+ isActive = true;
+ }
+ if (mNetworkActive != isActive) {
+ mNetworkActive = isActive;
+ report = isActive;
+ }
+ }
+ if (report) {
+ reportNetworkActive();
}
}
@@ -519,8 +553,7 @@
return;
}
// No current code examines the interface parameter in a global alert. Just pass null.
- mDaemonHandler.post(() -> mNetworkObserverRegistry.notifyLimitReached(
- LIMIT_GLOBAL_ALERT, null));
+ mDaemonHandler.post(() -> notifyLimitReached(LIMIT_GLOBAL_ALERT, null));
}
}
@@ -552,11 +585,10 @@
private void connectNativeNetdService() {
mNetdService = mServices.getNetd();
try {
- mNetworkObserverRegistry = new NMSNetworkObserverRegistry(
- mContext, mDaemonHandler, mNetdService);
- if (DBG) Slog.d(TAG, "Registered NetworkObserverRegistry");
+ mNetdService.registerUnsolicitedEventListener(mNetdUnsolicitedEventListener);
+ if (DBG) Slog.d(TAG, "Register unsolicited event listener");
} catch (RemoteException | ServiceSpecificException e) {
- Slog.wtf(TAG, "Failed to register NetworkObserverRegistry: " + e);
+ Slog.e(TAG, "Failed to set Netd unsolicited event listener " + e);
}
}
@@ -660,6 +692,118 @@
}
+ /**
+ * Notify our observers of a new or updated interface address.
+ */
+ private void notifyAddressUpdated(String iface, LinkAddress address) {
+ invokeForAllObservers(o -> o.addressUpdated(iface, address));
+ }
+
+ /**
+ * Notify our observers of a deleted interface address.
+ */
+ private void notifyAddressRemoved(String iface, LinkAddress address) {
+ invokeForAllObservers(o -> o.addressRemoved(iface, address));
+ }
+
+ /**
+ * Notify our observers of DNS server information received.
+ */
+ private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
+ invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses));
+ }
+
+ /**
+ * Notify our observers of a route change.
+ */
+ private void notifyRouteChange(boolean updated, RouteInfo route) {
+ if (updated) {
+ invokeForAllObservers(o -> o.routeUpdated(route));
+ } else {
+ invokeForAllObservers(o -> o.routeRemoved(route));
+ }
+ }
+
+ private class NetdUnsolicitedEventListener extends INetdUnsolicitedEventListener.Stub {
+ @Override
+ public void onInterfaceClassActivityChanged(boolean isActive,
+ int label, long timestamp, int uid) throws RemoteException {
+ final long timestampNanos;
+ if (timestamp <= 0) {
+ timestampNanos = SystemClock.elapsedRealtimeNanos();
+ } else {
+ timestampNanos = timestamp;
+ }
+ mDaemonHandler.post(() ->
+ notifyInterfaceClassActivity(label, isActive, timestampNanos, uid, false));
+ }
+
+ @Override
+ public void onQuotaLimitReached(String alertName, String ifName)
+ throws RemoteException {
+ mDaemonHandler.post(() -> notifyLimitReached(alertName, ifName));
+ }
+
+ @Override
+ public void onInterfaceDnsServerInfo(String ifName,
+ long lifetime, String[] servers) throws RemoteException {
+ mDaemonHandler.post(() -> notifyInterfaceDnsServerInfo(ifName, lifetime, servers));
+ }
+
+ @Override
+ public void onInterfaceAddressUpdated(String addr,
+ String ifName, int flags, int scope) throws RemoteException {
+ final LinkAddress address = new LinkAddress(addr, flags, scope);
+ mDaemonHandler.post(() -> notifyAddressUpdated(ifName, address));
+ }
+
+ @Override
+ public void onInterfaceAddressRemoved(String addr,
+ String ifName, int flags, int scope) throws RemoteException {
+ final LinkAddress address = new LinkAddress(addr, flags, scope);
+ mDaemonHandler.post(() -> notifyAddressRemoved(ifName, address));
+ }
+
+ @Override
+ public void onInterfaceAdded(String ifName) throws RemoteException {
+ mDaemonHandler.post(() -> notifyInterfaceAdded(ifName));
+ }
+
+ @Override
+ public void onInterfaceRemoved(String ifName) throws RemoteException {
+ mDaemonHandler.post(() -> notifyInterfaceRemoved(ifName));
+ }
+
+ @Override
+ public void onInterfaceChanged(String ifName, boolean up)
+ throws RemoteException {
+ mDaemonHandler.post(() -> notifyInterfaceStatusChanged(ifName, up));
+ }
+
+ @Override
+ public void onInterfaceLinkStateChanged(String ifName, boolean up)
+ throws RemoteException {
+ mDaemonHandler.post(() -> notifyInterfaceLinkStateChanged(ifName, up));
+ }
+
+ @Override
+ public void onRouteChanged(boolean updated,
+ String route, String gateway, String ifName) throws RemoteException {
+ final RouteInfo processRoute = new RouteInfo(new IpPrefix(route),
+ ("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway),
+ ifName);
+ mDaemonHandler.post(() -> notifyRouteChange(updated, processRoute));
+ }
+
+ @Override
+ public void onStrictCleartextDetected(int uid, String hex) throws RemoteException {
+ // Don't need to post to mDaemonHandler because the only thing
+ // that notifyCleartextNetwork does is post to a handler
+ ActivityManager.getService().notifyCleartextNetwork(uid,
+ HexDump.hexStringToByteArray(hex));
+ }
+ }
+
//
// Netd Callback handling
//
@@ -708,18 +852,16 @@
throw new IllegalStateException(errorMessage);
}
if (cooked[2].equals("added")) {
- mNetworkObserverRegistry.notifyInterfaceAdded(cooked[3]);
+ notifyInterfaceAdded(cooked[3]);
return true;
} else if (cooked[2].equals("removed")) {
- mNetworkObserverRegistry.notifyInterfaceRemoved(cooked[3]);
+ notifyInterfaceRemoved(cooked[3]);
return true;
} else if (cooked[2].equals("changed") && cooked.length == 5) {
- mNetworkObserverRegistry.notifyInterfaceStatusChanged(
- cooked[3], cooked[4].equals("up"));
+ notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
return true;
} else if (cooked[2].equals("linkstate") && cooked.length == 5) {
- mNetworkObserverRegistry.notifyInterfaceLinkStateChanged(
- cooked[3], cooked[4].equals("up"));
+ notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
return true;
}
throw new IllegalStateException(errorMessage);
@@ -733,7 +875,7 @@
throw new IllegalStateException(errorMessage);
}
if (cooked[2].equals("alert")) {
- mNetworkObserverRegistry.notifyLimitReached(cooked[3], cooked[4]);
+ notifyLimitReached(cooked[3], cooked[4]);
return true;
}
throw new IllegalStateException(errorMessage);
@@ -759,9 +901,8 @@
timestampNanos = SystemClock.elapsedRealtimeNanos();
}
boolean isActive = cooked[2].equals("active");
- mNetworkObserverRegistry.notifyInterfaceClassActivity(
- Integer.parseInt(cooked[3]), isActive,
- timestampNanos, processUid, false);
+ notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),
+ isActive, timestampNanos, processUid, false);
return true;
// break;
case NetdResponseCode.InterfaceAddressChange:
@@ -787,9 +928,9 @@
}
if (cooked[2].equals("updated")) {
- mNetworkObserverRegistry.notifyAddressUpdated(iface, address);
+ notifyAddressUpdated(iface, address);
} else {
- mNetworkObserverRegistry.notifyAddressRemoved(iface, address);
+ notifyAddressRemoved(iface, address);
}
return true;
// break;
@@ -809,8 +950,7 @@
throw new IllegalStateException(errorMessage);
}
String[] servers = cooked[5].split(",");
- mNetworkObserverRegistry.notifyInterfaceDnsServerInfo(
- cooked[3], lifetime, servers);
+ notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers);
}
return true;
// break;
@@ -849,8 +989,7 @@
InetAddress gateway = null;
if (via != null) gateway = InetAddress.parseNumericAddress(via);
RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);
- mNetworkObserverRegistry.notifyRouteChange(
- cooked[2].equals("updated"), route);
+ notifyRouteChange(cooked[2].equals("updated"), route);
return true;
} catch (IllegalArgumentException e) {}
}
@@ -1313,8 +1452,8 @@
if (ConnectivityManager.isNetworkTypeMobile(type)) {
mNetworkActive = false;
}
- mDaemonHandler.post(() -> mNetworkObserverRegistry.notifyInterfaceClassActivity(
- type, true /* isActive */, SystemClock.elapsedRealtimeNanos(), -1, false));
+ mDaemonHandler.post(() -> notifyInterfaceClassActivity(type, true,
+ SystemClock.elapsedRealtimeNanos(), -1, false));
}
}
@@ -1337,9 +1476,8 @@
throw new IllegalStateException(e);
}
mActiveIdleTimers.remove(iface);
- mDaemonHandler.post(() -> mNetworkObserverRegistry.notifyInterfaceClassActivity(
- params.type, false /* isActive */, SystemClock.elapsedRealtimeNanos(), -1,
- false));
+ mDaemonHandler.post(() -> notifyInterfaceClassActivity(params.type, false,
+ SystemClock.elapsedRealtimeNanos(), -1, false));
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 8f5d36a..31e1e35 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1852,7 +1852,11 @@
}
AlarmManager getAlarmManager() {
- return (AlarmManager) mContext.getSystemService(AlarmManager.class);
+ return mContext.getSystemService(AlarmManager.class);
+ }
+
+ ConnectivityManager getConnectivityManager() {
+ return mContext.getSystemService(ConnectivityManager.class);
}
IWindowManager getIWindowManager() {
@@ -5881,7 +5885,8 @@
* @throws UnsupportedOperationException if the package does not support being set as always-on.
*/
@Override
- public boolean setAlwaysOnVpnPackage(ComponentName admin, String vpnPackage, boolean lockdown)
+ public boolean setAlwaysOnVpnPackage(ComponentName admin, String vpnPackage, boolean lockdown,
+ List<String> lockdownWhitelist)
throws SecurityException {
enforceProfileOrDeviceOwner(admin);
@@ -5889,11 +5894,23 @@
final long token = mInjector.binderClearCallingIdentity();
try {
if (vpnPackage != null && !isPackageInstalledForUser(vpnPackage, userId)) {
- return false;
+ Slog.w(LOG_TAG, "Non-existent VPN package specified: " + vpnPackage);
+ throw new ServiceSpecificException(
+ DevicePolicyManager.ERROR_VPN_PACKAGE_NOT_FOUND, vpnPackage);
}
- ConnectivityManager connectivityManager = (ConnectivityManager)
- mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- if (!connectivityManager.setAlwaysOnVpnPackageForUser(userId, vpnPackage, lockdown)) {
+
+ if (vpnPackage != null && lockdown && lockdownWhitelist != null) {
+ for (String packageName : lockdownWhitelist) {
+ if (!isPackageInstalledForUser(packageName, userId)) {
+ Slog.w(LOG_TAG, "Non-existent package in VPN whitelist: " + packageName);
+ throw new ServiceSpecificException(
+ DevicePolicyManager.ERROR_VPN_PACKAGE_NOT_FOUND, packageName);
+ }
+ }
+ }
+ // If some package is uninstalled after the check above, it will be ignored by CM.
+ if (!mInjector.getConnectivityManager().setAlwaysOnVpnPackageForUser(
+ userId, vpnPackage, lockdown, lockdownWhitelist)) {
throw new UnsupportedOperationException();
}
} finally {
@@ -5903,16 +5920,40 @@
}
@Override
- public String getAlwaysOnVpnPackage(ComponentName admin)
+ public String getAlwaysOnVpnPackage(ComponentName admin) throws SecurityException {
+ enforceProfileOrDeviceOwner(admin);
+
+ final int userId = mInjector.userHandleGetCallingUserId();
+ final long token = mInjector.binderClearCallingIdentity();
+ try {
+ return mInjector.getConnectivityManager().getAlwaysOnVpnPackageForUser(userId);
+ } finally {
+ mInjector.binderRestoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public boolean isAlwaysOnVpnLockdownEnabled(ComponentName admin) throws SecurityException {
+ enforceProfileOrDeviceOwner(admin);
+
+ final int userId = mInjector.userHandleGetCallingUserId();
+ final long token = mInjector.binderClearCallingIdentity();
+ try {
+ return mInjector.getConnectivityManager().isVpnLockdownEnabled(userId);
+ } finally {
+ mInjector.binderRestoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public List<String> getAlwaysOnVpnLockdownWhitelist(ComponentName admin)
throws SecurityException {
enforceProfileOrDeviceOwner(admin);
final int userId = mInjector.userHandleGetCallingUserId();
final long token = mInjector.binderClearCallingIdentity();
- try{
- ConnectivityManager connectivityManager = (ConnectivityManager)
- mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- return connectivityManager.getAlwaysOnVpnPackageForUser(userId);
+ try {
+ return mInjector.getConnectivityManager().getVpnLockdownWhitelist(userId);
} finally {
mInjector.binderRestoreCallingIdentity(token);
}
@@ -6382,9 +6423,7 @@
}
long token = mInjector.binderClearCallingIdentity();
try {
- ConnectivityManager connectivityManager = (ConnectivityManager)
- mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- connectivityManager.setGlobalProxy(proxyInfo);
+ mInjector.getConnectivityManager().setGlobalProxy(proxyInfo);
} finally {
mInjector.binderRestoreCallingIdentity(token);
}
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/NetworkObserverRegistry.java b/services/net/java/android/net/shared/NetworkObserverRegistry.java
deleted file mode 100644
index 36945f5..0000000
--- a/services/net/java/android/net/shared/NetworkObserverRegistry.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net.shared;
-
-import static android.Manifest.permission.NETWORK_STACK;
-
-import android.content.Context;
-import android.net.INetd;
-import android.net.INetdUnsolicitedEventListener;
-import android.net.INetworkManagementEventObserver;
-import android.net.InetAddresses;
-import android.net.IpPrefix;
-import android.net.LinkAddress;
-import android.net.RouteInfo;
-import android.os.Handler;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.os.SystemClock;
-
-/**
- * A class for reporting network events to clients.
- *
- * Implements INetdUnsolicitedEventListener and registers with netd, and relays those events to
- * all INetworkManagementEventObserver objects that have registered with it.
- *
- * TODO: Make the notifyXyz methods protected once subclasses (e.g., the NetworkManagementService
- * subclass) no longer call them directly.
- *
- * TODO: change from RemoteCallbackList to direct in-process callbacks.
- */
-public class NetworkObserverRegistry extends INetdUnsolicitedEventListener.Stub {
-
- private final Context mContext;
- private final Handler mDaemonHandler;
- private static final String TAG = "NetworkObserverRegistry";
-
- /**
- * Constructs a new instance and registers it with netd.
- * This method should only be called once since netd will reject multiple registrations from
- * the same process.
- */
- public NetworkObserverRegistry(Context context, Handler handler, INetd netd)
- throws RemoteException {
- mContext = context;
- mDaemonHandler = handler;
- netd.registerUnsolicitedEventListener(this);
- }
-
- private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
- new RemoteCallbackList<>();
-
- /**
- * Registers the specified observer and start sending callbacks to it.
- * This method may be called on any thread.
- */
- public void registerObserver(INetworkManagementEventObserver observer) {
- mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
- mObservers.register(observer);
- }
-
- /**
- * Unregisters the specified observer and stop sending callbacks to it.
- * This method may be called on any thread.
- */
- public void unregisterObserver(INetworkManagementEventObserver observer) {
- mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
- mObservers.unregister(observer);
- }
-
- @FunctionalInterface
- private interface NetworkManagementEventCallback {
- void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
- }
-
- private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
- final int length = mObservers.beginBroadcast();
- try {
- for (int i = 0; i < length; i++) {
- try {
- eventCallback.sendCallback(mObservers.getBroadcastItem(i));
- } catch (RemoteException | RuntimeException e) {
- }
- }
- } finally {
- mObservers.finishBroadcast();
- }
- }
-
- /**
- * Notify our observers of a change in the data activity state of the interface
- */
- public void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos,
- int uid, boolean fromRadio) {
- invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
- Integer.toString(type), isActive, tsNanos));
- }
-
- @Override
- public void onInterfaceClassActivityChanged(boolean isActive,
- int label, long timestamp, int uid) throws RemoteException {
- final long timestampNanos;
- if (timestamp <= 0) {
- timestampNanos = SystemClock.elapsedRealtimeNanos();
- } else {
- timestampNanos = timestamp;
- }
- mDaemonHandler.post(() -> notifyInterfaceClassActivity(label, isActive,
- timestampNanos, uid, false));
- }
-
- /**
- * Notify our observers of a limit reached.
- */
- @Override
- public void onQuotaLimitReached(String alertName, String ifName) throws RemoteException {
- mDaemonHandler.post(() -> notifyLimitReached(alertName, ifName));
- }
-
- /**
- * Notify our observers of a limit reached.
- */
- public void notifyLimitReached(String limitName, String iface) {
- invokeForAllObservers(o -> o.limitReached(limitName, iface));
- }
-
- @Override
- public void onInterfaceDnsServerInfo(String ifName,
- long lifetime, String[] servers) throws RemoteException {
- mDaemonHandler.post(() -> notifyInterfaceDnsServerInfo(ifName, lifetime, servers));
- }
-
- /**
- * Notify our observers of DNS server information received.
- */
- public void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
- invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses));
- }
-
- @Override
- public void onInterfaceAddressUpdated(String addr,
- String ifName, int flags, int scope) throws RemoteException {
- final LinkAddress address = new LinkAddress(addr, flags, scope);
- mDaemonHandler.post(() -> notifyAddressUpdated(ifName, address));
- }
-
- /**
- * Notify our observers of a new or updated interface address.
- */
- public void notifyAddressUpdated(String iface, LinkAddress address) {
- invokeForAllObservers(o -> o.addressUpdated(iface, address));
- }
-
- @Override
- public void onInterfaceAddressRemoved(String addr,
- String ifName, int flags, int scope) throws RemoteException {
- final LinkAddress address = new LinkAddress(addr, flags, scope);
- mDaemonHandler.post(() -> notifyAddressRemoved(ifName, address));
- }
-
- /**
- * Notify our observers of a deleted interface address.
- */
- public void notifyAddressRemoved(String iface, LinkAddress address) {
- invokeForAllObservers(o -> o.addressRemoved(iface, address));
- }
-
-
- @Override
- public void onInterfaceAdded(String ifName) throws RemoteException {
- mDaemonHandler.post(() -> notifyInterfaceAdded(ifName));
- }
-
- /**
- * Notify our observers of an interface addition.
- */
- public void notifyInterfaceAdded(String iface) {
- invokeForAllObservers(o -> o.interfaceAdded(iface));
- }
-
- @Override
- public void onInterfaceRemoved(String ifName) throws RemoteException {
- mDaemonHandler.post(() -> notifyInterfaceRemoved(ifName));
- }
-
- /**
- * Notify our observers of an interface removal.
- */
- public void notifyInterfaceRemoved(String iface) {
- invokeForAllObservers(o -> o.interfaceRemoved(iface));
- }
-
- @Override
- public void onInterfaceChanged(String ifName, boolean up) throws RemoteException {
- mDaemonHandler.post(() -> notifyInterfaceStatusChanged(ifName, up));
- }
-
- /**
- * Notify our observers of an interface status change
- */
- public void notifyInterfaceStatusChanged(String iface, boolean up) {
- invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
- }
-
- @Override
- public void onInterfaceLinkStateChanged(String ifName, boolean up) throws RemoteException {
- mDaemonHandler.post(() -> notifyInterfaceLinkStateChanged(ifName, up));
- }
-
- /**
- * Notify our observers of an interface link state change
- * (typically, an Ethernet cable has been plugged-in or unplugged).
- */
- public void notifyInterfaceLinkStateChanged(String iface, boolean up) {
- invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
- }
-
- @Override
- public void onRouteChanged(boolean updated,
- String route, String gateway, String ifName) throws RemoteException {
- final RouteInfo processRoute = new RouteInfo(new IpPrefix(route),
- ("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway),
- ifName);
- mDaemonHandler.post(() -> notifyRouteChange(updated, processRoute));
- }
-
- /**
- * Notify our observers of a route change.
- */
- public void notifyRouteChange(boolean updated, RouteInfo route) {
- if (updated) {
- invokeForAllObservers(o -> o.routeUpdated(route));
- } else {
- invokeForAllObservers(o -> o.routeRemoved(route));
- }
- }
-
- @Override
- public void onStrictCleartextDetected(int uid, String hex) throws RemoteException {
- // Don't do anything here because this is not a method of INetworkManagementEventObserver.
- // Only the NMS subclass will implement this.
- }
-}
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/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index 7b23061..157f12c 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -16,7 +16,9 @@
package android.telecom;
+import android.annotation.FloatRange;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -364,7 +366,7 @@
* @param width The width of the camera video (in pixels).
* @param height The height of the camera video (in pixels).
*/
- public CameraCapabilities(int width, int height) {
+ public CameraCapabilities(@IntRange(from = 0) int width, @IntRange(from = 0) int height) {
this(width, height, false, 1.0f);
}
@@ -376,7 +378,8 @@
* @param zoomSupported True when camera supports zoom.
* @param maxZoom Maximum zoom supported by camera.
*/
- public CameraCapabilities(int width, int height, boolean zoomSupported, float maxZoom) {
+ public CameraCapabilities(@IntRange(from = 0) int width, @IntRange(from = 0) int height,
+ boolean zoomSupported, @FloatRange(from = 1.0f) float maxZoom) {
mWidth = width;
mHeight = height;
mZoomSupported = zoomSupported;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 26cba77..190e82b 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2371,33 +2371,54 @@
"support_emergency_dialer_shortcut_bool";
/**
- * Controls RSRP threshold at which AlternativeNetworkService will decide whether
+ * Controls RSRP threshold at which OpportunisticNetworkService will decide whether
* the opportunistic network is good enough for internet data.
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSRP_INT =
"opportunistic_network_entry_threshold_rsrp_int";
/**
- * Controls RSSNR threshold at which AlternativeNetworkService will decide whether
+ * Controls RSSNR threshold at which OpportunisticNetworkService will decide whether
* the opportunistic network is good enough for internet data.
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT =
"opportunistic_network_entry_threshold_rssnr_int";
/**
- * Controls RSRP threshold below which AlternativeNetworkService will decide whether
+ * Controls RSRP threshold below which OpportunisticNetworkService will decide whether
* the opportunistic network available is not good enough for internet data.
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT =
"opportunistic_network_exit_threshold_rsrp_int";
/**
- * Controls RSSNR threshold below which AlternativeNetworkService will decide whether
+ * Controls RSSNR threshold below which OpportunisticNetworkService will decide whether
* the opportunistic network available is not good enough for internet data.
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT =
"opportunistic_network_exit_threshold_rssnr_int";
+ /**
+ * Controls bandwidth threshold in Kbps at which OpportunisticNetworkService will decide whether
+ * the opportunistic network is good enough for internet data.
+ */
+ public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_BANDWIDTH_INT =
+ "opportunistic_network_entry_threshold_bandwidth_int";
+
+ /**
+ * Controls hysteresis time in milli seconds for which OpportunisticNetworkService
+ * will wait before attaching to a network.
+ */
+ public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_OR_EXIT_HYSTERESIS_TIME_LONG =
+ "opportunistic_network_entry_or_exit_hysteresis_time_long";
+
+ /**
+ * Controls hysteresis time in milli seconds for which OpportunisticNetworkService
+ * will wait before switching data to a network.
+ */
+ public static final String KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG =
+ "opportunistic_network_data_switch_hysteresis_time_long";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -2767,6 +2788,12 @@
sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT, 45);
/* Default value is minimum RSSNR level needed for SIGNAL_STRENGTH_MODERATE */
sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT, 10);
+ /* Default value is 1024 kbps */
+ sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_BANDWIDTH_INT, 1024);
+ /* Default value is 10 seconds */
+ sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_OR_EXIT_HYSTERESIS_TIME_LONG, 10000);
+ /* Default value is 10 seconds. */
+ sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG, 10000);
}
/**
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/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 4e4ef4d..443f908 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -577,10 +577,10 @@
}
/**
- * @return the cardId of the SIM card which contains the subscription.
- * @hide
+ * Returns the card ID of the SIM card which contains the subscription (see
+ * {@link UiccCardInfo#getCardId()}.
+ * @return the cardId
*/
- @SystemApi
public int getCardId() {
return this.mCardId;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 2461aad..5c86efb 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -227,10 +227,9 @@
public static final int SRVCC_STATE_HANDOVER_CANCELED = 3;
/**
- * An invalid card identifier.
- * @hide
+ * An invalid UICC card identifier. See {@link #getCardIdForDefaultEuicc()} and
+ * {@link UiccCardInfo#getCardId()}.
*/
- @SystemApi
public static final int INVALID_CARD_ID = -1;
/** @hide */
@@ -3118,14 +3117,8 @@
* unique to a device, and always refer to the same UICC or eUICC card unless the device goes
* through a factory reset.
*
- * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
- *
* @return card ID of the default eUICC card.
- * @hide
*/
- @SystemApi
- @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public int getCardIdForDefaultEuicc() {
try {
ITelephony telephony = getITelephony();
@@ -3139,25 +3132,37 @@
}
/**
- * Gets information about currently inserted UICCs and eUICCs. See {@link UiccCardInfo} for more
- * details on the kind of information available.
+ * Gets information about currently inserted UICCs and enabled eUICCs.
+ * <p>
+ * Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ * <p>
+ * If the caller has carrier priviliges on any active subscription, then they have permission to
+ * get simple information like the card ID ({@link UiccCardInfo#getCardId()}), whether the card
+ * is an eUICC ({@link UiccCardInfo#isEuicc()}), and the slot index where the card is inserted
+ * ({@link UiccCardInfo#getSlotIndex()}).
+ * <p>
+ * To get private information such as the EID ({@link UiccCardInfo#getEid()}) or ICCID
+ * ({@link UiccCardInfo#getIccId()}), the caller must have carrier priviliges on that specific
+ * UICC or eUICC card.
+ * <p>
+ * See {@link UiccCardInfo} for more details on the kind of information available.
*
- * @return UiccCardInfo an array of UiccCardInfo objects, representing information on the
- * currently inserted UICCs and eUICCs.
- *
- * @hide
+ * @return a list of UiccCardInfo objects, representing information on the currently inserted
+ * UICCs and eUICCs. Each UiccCardInfo in the list will have private information filtered out if
+ * the caller does not have adequate permissions for that card.
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public UiccCardInfo[] getUiccCardsInfo() {
+ public List<UiccCardInfo> getUiccCardsInfo() {
try {
ITelephony telephony = getITelephony();
if (telephony == null) {
- return null;
+ Log.e(TAG, "Error in getUiccCardsInfo: unable to connect to Telephony service.");
+ return new ArrayList<UiccCardInfo>();
}
- return telephony.getUiccCardsInfo();
+ return telephony.getUiccCardsInfo(mContext.getOpPackageName());
} catch (RemoteException e) {
- return null;
+ Log.e(TAG, "Error in getUiccCardsInfo: " + e);
+ return new ArrayList<UiccCardInfo>();
}
}
@@ -8949,6 +8954,9 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public int setAllowedCarriers(int slotIndex, List<CarrierIdentifier> carriers) {
+ if (carriers == null || !SubscriptionManager.isValidPhoneId(slotIndex)) {
+ return -1;
+ }
// Execute the method setCarrierRestrictionRules with an empty excluded list and
// indicating priority for the allowed list.
CarrierRestrictionRules carrierRestrictionRules = CarrierRestrictionRules.newBuilder()
@@ -8959,7 +8967,7 @@
int result = setCarrierRestrictionRules(carrierRestrictionRules);
- // Convert boolean result into int, as required by this method.
+ // Convert result into int, as required by this method.
if (result == SET_CARRIER_RESTRICTION_SUCCESS) {
return carriers.size();
} else {
@@ -9052,9 +9060,11 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public List<CarrierIdentifier> getAllowedCarriers(int slotIndex) {
- CarrierRestrictionRules carrierRestrictionRule = getCarrierRestrictionRules();
- if (carrierRestrictionRule != null) {
- return carrierRestrictionRule.getAllowedCarriers();
+ if (SubscriptionManager.isValidPhoneId(slotIndex)) {
+ CarrierRestrictionRules carrierRestrictionRule = getCarrierRestrictionRules();
+ if (carrierRestrictionRule != null) {
+ return carrierRestrictionRule.getAllowedCarriers();
+ }
}
return new ArrayList<CarrierIdentifier>(0);
}
@@ -9971,4 +9981,52 @@
}
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;
+ }
}
diff --git a/telephony/java/android/telephony/UiccCardInfo.java b/telephony/java/android/telephony/UiccCardInfo.java
index 45e4704..19f357a 100644
--- a/telephony/java/android/telephony/UiccCardInfo.java
+++ b/telephony/java/android/telephony/UiccCardInfo.java
@@ -15,7 +15,6 @@
*/
package android.telephony;
-import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -23,10 +22,8 @@
/**
* The UiccCardInfo represents information about a currently inserted UICC or embedded eUICC.
- * @hide
*/
-@SystemApi
-public class UiccCardInfo implements Parcelable {
+public final class UiccCardInfo implements Parcelable {
private final boolean mIsEuicc;
private final int mCardId;
@@ -95,6 +92,9 @@
/**
* Get the embedded ID (EID) of the eUICC. If the UiccCardInfo is not an eUICC
* (see {@link #isEuicc()}), returns null.
+ * <p>
+ * Note that this field may be omitted if the caller does not have the correct permissions
+ * (see {@link TelephonyManager#getUiccCardsInfo()}).
*/
public String getEid() {
if (!mIsEuicc) {
@@ -105,6 +105,9 @@
/**
* Get the ICCID of the UICC.
+ * <p>
+ * Note that this field may be omitted if the caller does not have the correct permissions
+ * (see {@link TelephonyManager#getUiccCardsInfo()}).
*/
public String getIccId() {
return mIccId;
@@ -117,6 +120,16 @@
return mSlotIndex;
}
+ /**
+ * Returns a copy of the UiccCardinfo with the clears the EID and ICCID set to null. These
+ * values are generally private and require carrier privileges to view.
+ *
+ * @hide
+ */
+ public UiccCardInfo getUnprivileged() {
+ return new UiccCardInfo(mIsEuicc, mCardId, null, null, mSlotIndex);
+ }
+
@Override
public boolean equals(Object obj) {
if (this == obj) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index d381514..a12792a 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1484,25 +1484,34 @@
* Get the card ID of the default eUICC card. If there is no eUICC, returns
* {@link #INVALID_CARD_ID}.
*
- * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
- *
* @param subId subscription ID used for authentication
* @param callingPackage package making the call
* @return card ID of the default eUICC card.
- * @hide
*/
- int getCardIdForDefaultEuicc(int subId, String callingPackage);
+ int getCardIdForDefaultEuicc(int subId, String callingPackage);
/**
- * Gets information about currently inserted UICCs and eUICCs. See {@link UiccCardInfo} for more
- * details on the kind of information available.
+ * Gets information about currently inserted UICCs and enabled eUICCs.
+ * <p>
+ * Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ * <p>
+ * If the caller has carrier priviliges on any active subscription, then they have permission to
+ * get simple information like the card ID ({@link UiccCardInfo#getCardId()}), whether the card
+ * is an eUICC ({@link UiccCardInfo#isEuicc()}), and the slot index where the card is inserted
+ * ({@link UiccCardInfo#getSlotIndex()}).
+ * <p>
+ * To get private information such as the EID ({@link UiccCardInfo#getEid()}) or ICCID
+ * ({@link UiccCardInfo#getIccId()}), the caller must have carrier priviliges on that specific
+ * UICC or eUICC card.
+ * <p>
+ * See {@link UiccCardInfo} for more details on the kind of information available.
*
- * @return UiccCardInfo an array of UiccCardInfo objects, representing information on the
- * currently inserted UICCs and eUICCs.
- *
- * @hide
+ * @param callingPackage package making the call, used to evaluate carrier privileges
+ * @return a list of UiccCardInfo objects, representing information on the currently inserted
+ * UICCs and eUICCs. Each UiccCardInfo in the list will have private information filtered out if
+ * the caller does not have adequate permissions for that card.
*/
- UiccCardInfo[] getUiccCardsInfo();
+ List<UiccCardInfo> getUiccCardsInfo(String callingPackage);
/**
* Get slot info for all the UICC slots.
@@ -1808,4 +1817,16 @@
* 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();
}
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..036c5dc 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 {
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 75c3eba..59e89f5 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -223,6 +223,7 @@
class V2Tokenizer(object):
__slots__ = ["raw"]
+ SIGNATURE_PREFIX = "// Signature format: "
DELIMITER = re.compile(r'\s+|[()@<>;,={}/"!?]|\[\]|\.\.\.')
STRING_SPECIAL = re.compile(r'["\\]')
@@ -610,8 +611,12 @@
else:
blame = None
- if line == 1 and raw == "// Signature format: 2.0":
- sig_format = 2
+ if line == 1 and raw.startswith("// Signature format: "):
+ sig_format_string = raw[len(V2Tokenizer.SIGNATURE_PREFIX):]
+ if sig_format_string in ["2.0", "3.0"]:
+ sig_format = 2
+ else:
+ raise ValueError("Unknown format: %s" % (sig_format_string,))
elif raw.startswith("package"):
pkg = Package(line, raw, blame)
elif raw.startswith(" ") and raw.endswith("{"):
diff --git a/tools/apilint/apilint_test.py b/tools/apilint/apilint_test.py
index 9c261d5..3716bf9 100644
--- a/tools/apilint/apilint_test.py
+++ b/tools/apilint/apilint_test.py
@@ -164,6 +164,23 @@
self.assertEquals(api['android.SomeEnum'].ctors[0].split[0], 'ctor')
self.assertEquals(api['android.SomeEnum'].methods[0].split[0], 'method')
+class ParseV3Stream(unittest.TestCase):
+ def test_field_kinds(self):
+ api = apilint._parse_stream("""
+// Signature format: 3.0
+package a {
+
+ public final class ContextKt {
+ method public static inline <reified T> T! getSystemService(android.content.Context);
+ method public static inline void withStyledAttributes(android.content.Context, android.util.AttributeSet? set = null, int[] attrs, @AttrRes int defStyleAttr = 0, @StyleRes int defStyleRes = 0, kotlin.jvm.functions.Function1<? super android.content.res.TypedArray,kotlin.Unit> block);
+ }
+}
+ """.strip().split('\n'))
+ self.assertEquals(api['a.ContextKt'].methods[0].name, 'getSystemService')
+ self.assertEquals(api['a.ContextKt'].methods[0].split[:4], ['method', 'public', 'static', 'inline'])
+ self.assertEquals(api['a.ContextKt'].methods[1].name, 'withStyledAttributes')
+ self.assertEquals(api['a.ContextKt'].methods[1].split[:4], ['method', 'public', 'static', 'inline'])
+
class V2TokenizerTests(unittest.TestCase):
def _test(self, raw, expected):
self.assertEquals(apilint.V2Tokenizer(raw).tokenize(), expected)