Merge "Reduced the retry after disconnect delay"
diff --git a/api/current.txt b/api/current.txt
index 739e7f2..b232abb 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16686,6 +16686,7 @@
field public static final java.lang.String ABBR_UTC_TZ = "ZZZZ";
field public static final java.lang.String ABBR_WEEKDAY = "E";
field public static final int AM_PM_FIELD = 14; // 0xe
+ field public static final int AM_PM_MIDNIGHT_NOON_FIELD = 35; // 0x23
field public static final int DATE_FIELD = 3; // 0x3
field public static final java.lang.String DAY = "d";
field public static final int DAY_OF_WEEK_FIELD = 9; // 0x9
@@ -16695,6 +16696,7 @@
field public static final int DOW_LOCAL_FIELD = 19; // 0x13
field public static final int ERA_FIELD = 0; // 0x0
field public static final int EXTENDED_YEAR_FIELD = 20; // 0x14
+ field public static final int FLEXIBLE_DAY_PERIOD_FIELD = 36; // 0x24
field public static final int FRACTIONAL_SECOND_FIELD = 8; // 0x8
field public static final int FULL = 0; // 0x0
field public static final java.lang.String GENERIC_TZ = "vvvv";
@@ -16783,6 +16785,7 @@
method public int getCalendarField();
method public static android.icu.text.DateFormat.Field ofCalendarField(int);
field public static final android.icu.text.DateFormat.Field AM_PM;
+ field public static final android.icu.text.DateFormat.Field AM_PM_MIDNIGHT_NOON;
field public static final android.icu.text.DateFormat.Field DAY_OF_MONTH;
field public static final android.icu.text.DateFormat.Field DAY_OF_WEEK;
field public static final android.icu.text.DateFormat.Field DAY_OF_WEEK_IN_MONTH;
@@ -16790,6 +16793,7 @@
field public static final android.icu.text.DateFormat.Field DOW_LOCAL;
field public static final android.icu.text.DateFormat.Field ERA;
field public static final android.icu.text.DateFormat.Field EXTENDED_YEAR;
+ field public static final android.icu.text.DateFormat.Field FLEXIBLE_DAY_PERIOD;
field public static final android.icu.text.DateFormat.Field HOUR0;
field public static final android.icu.text.DateFormat.Field HOUR1;
field public static final android.icu.text.DateFormat.Field HOUR_OF_DAY0;
@@ -16961,70 +16965,70 @@
ctor public DecimalFormat(java.lang.String);
ctor public DecimalFormat(java.lang.String, android.icu.text.DecimalFormatSymbols);
ctor public DecimalFormat(java.lang.String, android.icu.text.DecimalFormatSymbols, android.icu.text.CurrencyPluralInfo, int);
- method public void applyLocalizedPattern(java.lang.String);
- method public void applyPattern(java.lang.String);
- method public boolean areSignificantDigitsUsed();
+ method public synchronized void applyLocalizedPattern(java.lang.String);
+ method public synchronized void applyPattern(java.lang.String);
+ method public synchronized boolean areSignificantDigitsUsed();
method public java.lang.StringBuffer format(double, java.lang.StringBuffer, java.text.FieldPosition);
method public java.lang.StringBuffer format(long, java.lang.StringBuffer, java.text.FieldPosition);
method public java.lang.StringBuffer format(java.math.BigInteger, java.lang.StringBuffer, java.text.FieldPosition);
method public java.lang.StringBuffer format(java.math.BigDecimal, java.lang.StringBuffer, java.text.FieldPosition);
method public java.lang.StringBuffer format(android.icu.math.BigDecimal, java.lang.StringBuffer, java.text.FieldPosition);
- method public android.icu.text.CurrencyPluralInfo getCurrencyPluralInfo();
- method public android.icu.util.Currency.CurrencyUsage getCurrencyUsage();
- method public android.icu.text.DecimalFormatSymbols getDecimalFormatSymbols();
- method public int getFormatWidth();
- method public int getGroupingSize();
- method public java.math.MathContext getMathContext();
- method public android.icu.math.MathContext getMathContextICU();
- method public int getMaximumSignificantDigits();
- method public byte getMinimumExponentDigits();
- method public int getMinimumSignificantDigits();
- method public int getMultiplier();
- method public java.lang.String getNegativePrefix();
- method public java.lang.String getNegativeSuffix();
- method public char getPadCharacter();
- method public int getPadPosition();
- method public int getParseMaxDigits();
- method public java.lang.String getPositivePrefix();
- method public java.lang.String getPositiveSuffix();
- method public java.math.BigDecimal getRoundingIncrement();
- method public int getSecondaryGroupingSize();
- method public boolean isDecimalPatternMatchRequired();
- method public boolean isDecimalSeparatorAlwaysShown();
- method public boolean isExponentSignAlwaysShown();
- method public boolean isParseBigDecimal();
- method public boolean isScientificNotation();
+ method public synchronized android.icu.text.CurrencyPluralInfo getCurrencyPluralInfo();
+ method public synchronized android.icu.util.Currency.CurrencyUsage getCurrencyUsage();
+ method public synchronized android.icu.text.DecimalFormatSymbols getDecimalFormatSymbols();
+ method public synchronized int getFormatWidth();
+ method public synchronized int getGroupingSize();
+ method public synchronized java.math.MathContext getMathContext();
+ method public synchronized android.icu.math.MathContext getMathContextICU();
+ method public synchronized int getMaximumSignificantDigits();
+ method public synchronized byte getMinimumExponentDigits();
+ method public synchronized int getMinimumSignificantDigits();
+ method public synchronized int getMultiplier();
+ method public synchronized java.lang.String getNegativePrefix();
+ method public synchronized java.lang.String getNegativeSuffix();
+ method public synchronized char getPadCharacter();
+ method public synchronized int getPadPosition();
+ method public deprecated int getParseMaxDigits();
+ method public synchronized java.lang.String getPositivePrefix();
+ method public synchronized java.lang.String getPositiveSuffix();
+ method public synchronized java.math.BigDecimal getRoundingIncrement();
+ method public synchronized int getSecondaryGroupingSize();
+ method public synchronized boolean isDecimalPatternMatchRequired();
+ method public synchronized boolean isDecimalSeparatorAlwaysShown();
+ method public synchronized boolean isExponentSignAlwaysShown();
+ method public synchronized boolean isParseBigDecimal();
+ method public synchronized boolean isScientificNotation();
method public java.lang.Number parse(java.lang.String, java.text.ParsePosition);
- method public void setCurrencyPluralInfo(android.icu.text.CurrencyPluralInfo);
- method public void setCurrencyUsage(android.icu.util.Currency.CurrencyUsage);
- method public void setDecimalFormatSymbols(android.icu.text.DecimalFormatSymbols);
- method public void setDecimalPatternMatchRequired(boolean);
- method public void setDecimalSeparatorAlwaysShown(boolean);
- method public void setExponentSignAlwaysShown(boolean);
- method public void setFormatWidth(int);
- method public void setGroupingSize(int);
- method public void setMathContext(java.math.MathContext);
- method public void setMathContextICU(android.icu.math.MathContext);
- method public void setMaximumSignificantDigits(int);
- method public void setMinimumExponentDigits(byte);
- method public void setMinimumSignificantDigits(int);
- method public void setMultiplier(int);
- method public void setNegativePrefix(java.lang.String);
- method public void setNegativeSuffix(java.lang.String);
- method public void setPadCharacter(char);
- method public void setPadPosition(int);
- method public void setParseBigDecimal(boolean);
- method public void setParseMaxDigits(int);
- method public void setPositivePrefix(java.lang.String);
- method public void setPositiveSuffix(java.lang.String);
- method public void setRoundingIncrement(java.math.BigDecimal);
- method public void setRoundingIncrement(android.icu.math.BigDecimal);
- method public void setRoundingIncrement(double);
- method public void setScientificNotation(boolean);
- method public void setSecondaryGroupingSize(int);
- method public void setSignificantDigitsUsed(boolean);
- method public java.lang.String toLocalizedPattern();
- method public java.lang.String toPattern();
+ method public synchronized void setCurrencyPluralInfo(android.icu.text.CurrencyPluralInfo);
+ method public synchronized void setCurrencyUsage(android.icu.util.Currency.CurrencyUsage);
+ method public synchronized void setDecimalFormatSymbols(android.icu.text.DecimalFormatSymbols);
+ method public synchronized void setDecimalPatternMatchRequired(boolean);
+ method public synchronized void setDecimalSeparatorAlwaysShown(boolean);
+ method public synchronized void setExponentSignAlwaysShown(boolean);
+ method public synchronized void setFormatWidth(int);
+ method public synchronized void setGroupingSize(int);
+ method public synchronized void setMathContext(java.math.MathContext);
+ method public synchronized void setMathContextICU(android.icu.math.MathContext);
+ method public synchronized void setMaximumSignificantDigits(int);
+ method public synchronized void setMinimumExponentDigits(byte);
+ method public synchronized void setMinimumSignificantDigits(int);
+ method public synchronized void setMultiplier(int);
+ method public synchronized void setNegativePrefix(java.lang.String);
+ method public synchronized void setNegativeSuffix(java.lang.String);
+ method public synchronized void setPadCharacter(char);
+ method public synchronized void setPadPosition(int);
+ method public synchronized void setParseBigDecimal(boolean);
+ method public deprecated void setParseMaxDigits(int);
+ method public synchronized void setPositivePrefix(java.lang.String);
+ method public synchronized void setPositiveSuffix(java.lang.String);
+ method public synchronized void setRoundingIncrement(java.math.BigDecimal);
+ method public synchronized void setRoundingIncrement(android.icu.math.BigDecimal);
+ method public synchronized void setRoundingIncrement(double);
+ method public synchronized void setScientificNotation(boolean);
+ method public synchronized void setSecondaryGroupingSize(int);
+ method public synchronized void setSignificantDigitsUsed(boolean);
+ method public synchronized java.lang.String toLocalizedPattern();
+ method public synchronized java.lang.String toPattern();
field public static final int PAD_AFTER_PREFIX = 1; // 0x1
field public static final int PAD_AFTER_SUFFIX = 3; // 0x3
field public static final int PAD_BEFORE_PREFIX = 0; // 0x0
@@ -17572,6 +17576,8 @@
method public java.lang.String combineDateAndTime(java.lang.String, java.lang.String);
method public java.lang.String format(double, android.icu.text.RelativeDateTimeFormatter.Direction, android.icu.text.RelativeDateTimeFormatter.RelativeUnit);
method public java.lang.String format(android.icu.text.RelativeDateTimeFormatter.Direction, android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit);
+ method public java.lang.String format(double, android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit);
+ method public java.lang.String formatNumeric(double, android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit);
method public android.icu.text.DisplayContext getCapitalizationContext();
method public android.icu.text.RelativeDateTimeFormatter.Style getFormatStyle();
method public static android.icu.text.RelativeDateTimeFormatter getInstance();
@@ -17611,6 +17617,26 @@
enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction THIS;
}
+ public static final class RelativeDateTimeFormatter.RelativeDateTimeUnit extends java.lang.Enum {
+ method public static android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit valueOf(java.lang.String);
+ method public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit[] values();
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit DAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit FRIDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit HOUR;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MINUTE;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MONDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MONTH;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit QUARTER;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SATURDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SECOND;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SUNDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit THURSDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit TUESDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit WEDNESDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit WEEK;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit YEAR;
+ }
+
public static final class RelativeDateTimeFormatter.RelativeUnit extends java.lang.Enum {
method public static android.icu.text.RelativeDateTimeFormatter.RelativeUnit valueOf(java.lang.String);
method public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit[] values();
@@ -18681,6 +18707,7 @@
field public static final android.icu.util.MeasureUnit FOOT;
field public static final android.icu.util.MeasureUnit FURLONG;
field public static final android.icu.util.MeasureUnit GALLON;
+ field public static final android.icu.util.MeasureUnit GALLON_IMPERIAL;
field public static final android.icu.util.MeasureUnit GENERIC_TEMPERATURE;
field public static final android.icu.util.MeasureUnit GIGABIT;
field public static final android.icu.util.MeasureUnit GIGABYTE;
@@ -18729,11 +18756,13 @@
field public static final android.icu.util.MeasureUnit MICROSECOND;
field public static final android.icu.util.MeasureUnit MILE;
field public static final android.icu.util.MeasureUnit MILE_PER_GALLON;
+ field public static final android.icu.util.MeasureUnit MILE_PER_GALLON_IMPERIAL;
field public static final android.icu.util.MeasureUnit MILE_PER_HOUR;
field public static final android.icu.util.MeasureUnit MILE_SCANDINAVIAN;
field public static final android.icu.util.MeasureUnit MILLIAMPERE;
field public static final android.icu.util.MeasureUnit MILLIBAR;
field public static final android.icu.util.MeasureUnit MILLIGRAM;
+ field public static final android.icu.util.MeasureUnit MILLIGRAM_PER_DECILITER;
field public static final android.icu.util.MeasureUnit MILLILITER;
field public static final android.icu.util.MeasureUnit MILLIMETER;
field public static final android.icu.util.MeasureUnit MILLIMETER_OF_MERCURY;
@@ -19037,7 +19066,7 @@
field public static final int JAVA_TIME = 0; // 0x0
field public static final int MAC_OLD_TIME = 5; // 0x5
field public static final int MAC_TIME = 6; // 0x6
- field public static final int MAX_SCALE = 10; // 0xa
+ field public static final deprecated int MAX_SCALE = 10; // 0xa
field public static final int TO_MAX_VALUE = 5; // 0x5
field public static final int TO_MIN_VALUE = 4; // 0x4
field public static final int UNITS_VALUE = 0; // 0x0
diff --git a/api/system-current.txt b/api/system-current.txt
index 0aa5d58..10b0221 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -17901,6 +17901,7 @@
field public static final java.lang.String ABBR_UTC_TZ = "ZZZZ";
field public static final java.lang.String ABBR_WEEKDAY = "E";
field public static final int AM_PM_FIELD = 14; // 0xe
+ field public static final int AM_PM_MIDNIGHT_NOON_FIELD = 35; // 0x23
field public static final int DATE_FIELD = 3; // 0x3
field public static final java.lang.String DAY = "d";
field public static final int DAY_OF_WEEK_FIELD = 9; // 0x9
@@ -17910,6 +17911,7 @@
field public static final int DOW_LOCAL_FIELD = 19; // 0x13
field public static final int ERA_FIELD = 0; // 0x0
field public static final int EXTENDED_YEAR_FIELD = 20; // 0x14
+ field public static final int FLEXIBLE_DAY_PERIOD_FIELD = 36; // 0x24
field public static final int FRACTIONAL_SECOND_FIELD = 8; // 0x8
field public static final int FULL = 0; // 0x0
field public static final java.lang.String GENERIC_TZ = "vvvv";
@@ -17998,6 +18000,7 @@
method public int getCalendarField();
method public static android.icu.text.DateFormat.Field ofCalendarField(int);
field public static final android.icu.text.DateFormat.Field AM_PM;
+ field public static final android.icu.text.DateFormat.Field AM_PM_MIDNIGHT_NOON;
field public static final android.icu.text.DateFormat.Field DAY_OF_MONTH;
field public static final android.icu.text.DateFormat.Field DAY_OF_WEEK;
field public static final android.icu.text.DateFormat.Field DAY_OF_WEEK_IN_MONTH;
@@ -18005,6 +18008,7 @@
field public static final android.icu.text.DateFormat.Field DOW_LOCAL;
field public static final android.icu.text.DateFormat.Field ERA;
field public static final android.icu.text.DateFormat.Field EXTENDED_YEAR;
+ field public static final android.icu.text.DateFormat.Field FLEXIBLE_DAY_PERIOD;
field public static final android.icu.text.DateFormat.Field HOUR0;
field public static final android.icu.text.DateFormat.Field HOUR1;
field public static final android.icu.text.DateFormat.Field HOUR_OF_DAY0;
@@ -18176,70 +18180,70 @@
ctor public DecimalFormat(java.lang.String);
ctor public DecimalFormat(java.lang.String, android.icu.text.DecimalFormatSymbols);
ctor public DecimalFormat(java.lang.String, android.icu.text.DecimalFormatSymbols, android.icu.text.CurrencyPluralInfo, int);
- method public void applyLocalizedPattern(java.lang.String);
- method public void applyPattern(java.lang.String);
- method public boolean areSignificantDigitsUsed();
+ method public synchronized void applyLocalizedPattern(java.lang.String);
+ method public synchronized void applyPattern(java.lang.String);
+ method public synchronized boolean areSignificantDigitsUsed();
method public java.lang.StringBuffer format(double, java.lang.StringBuffer, java.text.FieldPosition);
method public java.lang.StringBuffer format(long, java.lang.StringBuffer, java.text.FieldPosition);
method public java.lang.StringBuffer format(java.math.BigInteger, java.lang.StringBuffer, java.text.FieldPosition);
method public java.lang.StringBuffer format(java.math.BigDecimal, java.lang.StringBuffer, java.text.FieldPosition);
method public java.lang.StringBuffer format(android.icu.math.BigDecimal, java.lang.StringBuffer, java.text.FieldPosition);
- method public android.icu.text.CurrencyPluralInfo getCurrencyPluralInfo();
- method public android.icu.util.Currency.CurrencyUsage getCurrencyUsage();
- method public android.icu.text.DecimalFormatSymbols getDecimalFormatSymbols();
- method public int getFormatWidth();
- method public int getGroupingSize();
- method public java.math.MathContext getMathContext();
- method public android.icu.math.MathContext getMathContextICU();
- method public int getMaximumSignificantDigits();
- method public byte getMinimumExponentDigits();
- method public int getMinimumSignificantDigits();
- method public int getMultiplier();
- method public java.lang.String getNegativePrefix();
- method public java.lang.String getNegativeSuffix();
- method public char getPadCharacter();
- method public int getPadPosition();
- method public int getParseMaxDigits();
- method public java.lang.String getPositivePrefix();
- method public java.lang.String getPositiveSuffix();
- method public java.math.BigDecimal getRoundingIncrement();
- method public int getSecondaryGroupingSize();
- method public boolean isDecimalPatternMatchRequired();
- method public boolean isDecimalSeparatorAlwaysShown();
- method public boolean isExponentSignAlwaysShown();
- method public boolean isParseBigDecimal();
- method public boolean isScientificNotation();
+ method public synchronized android.icu.text.CurrencyPluralInfo getCurrencyPluralInfo();
+ method public synchronized android.icu.util.Currency.CurrencyUsage getCurrencyUsage();
+ method public synchronized android.icu.text.DecimalFormatSymbols getDecimalFormatSymbols();
+ method public synchronized int getFormatWidth();
+ method public synchronized int getGroupingSize();
+ method public synchronized java.math.MathContext getMathContext();
+ method public synchronized android.icu.math.MathContext getMathContextICU();
+ method public synchronized int getMaximumSignificantDigits();
+ method public synchronized byte getMinimumExponentDigits();
+ method public synchronized int getMinimumSignificantDigits();
+ method public synchronized int getMultiplier();
+ method public synchronized java.lang.String getNegativePrefix();
+ method public synchronized java.lang.String getNegativeSuffix();
+ method public synchronized char getPadCharacter();
+ method public synchronized int getPadPosition();
+ method public deprecated int getParseMaxDigits();
+ method public synchronized java.lang.String getPositivePrefix();
+ method public synchronized java.lang.String getPositiveSuffix();
+ method public synchronized java.math.BigDecimal getRoundingIncrement();
+ method public synchronized int getSecondaryGroupingSize();
+ method public synchronized boolean isDecimalPatternMatchRequired();
+ method public synchronized boolean isDecimalSeparatorAlwaysShown();
+ method public synchronized boolean isExponentSignAlwaysShown();
+ method public synchronized boolean isParseBigDecimal();
+ method public synchronized boolean isScientificNotation();
method public java.lang.Number parse(java.lang.String, java.text.ParsePosition);
- method public void setCurrencyPluralInfo(android.icu.text.CurrencyPluralInfo);
- method public void setCurrencyUsage(android.icu.util.Currency.CurrencyUsage);
- method public void setDecimalFormatSymbols(android.icu.text.DecimalFormatSymbols);
- method public void setDecimalPatternMatchRequired(boolean);
- method public void setDecimalSeparatorAlwaysShown(boolean);
- method public void setExponentSignAlwaysShown(boolean);
- method public void setFormatWidth(int);
- method public void setGroupingSize(int);
- method public void setMathContext(java.math.MathContext);
- method public void setMathContextICU(android.icu.math.MathContext);
- method public void setMaximumSignificantDigits(int);
- method public void setMinimumExponentDigits(byte);
- method public void setMinimumSignificantDigits(int);
- method public void setMultiplier(int);
- method public void setNegativePrefix(java.lang.String);
- method public void setNegativeSuffix(java.lang.String);
- method public void setPadCharacter(char);
- method public void setPadPosition(int);
- method public void setParseBigDecimal(boolean);
- method public void setParseMaxDigits(int);
- method public void setPositivePrefix(java.lang.String);
- method public void setPositiveSuffix(java.lang.String);
- method public void setRoundingIncrement(java.math.BigDecimal);
- method public void setRoundingIncrement(android.icu.math.BigDecimal);
- method public void setRoundingIncrement(double);
- method public void setScientificNotation(boolean);
- method public void setSecondaryGroupingSize(int);
- method public void setSignificantDigitsUsed(boolean);
- method public java.lang.String toLocalizedPattern();
- method public java.lang.String toPattern();
+ method public synchronized void setCurrencyPluralInfo(android.icu.text.CurrencyPluralInfo);
+ method public synchronized void setCurrencyUsage(android.icu.util.Currency.CurrencyUsage);
+ method public synchronized void setDecimalFormatSymbols(android.icu.text.DecimalFormatSymbols);
+ method public synchronized void setDecimalPatternMatchRequired(boolean);
+ method public synchronized void setDecimalSeparatorAlwaysShown(boolean);
+ method public synchronized void setExponentSignAlwaysShown(boolean);
+ method public synchronized void setFormatWidth(int);
+ method public synchronized void setGroupingSize(int);
+ method public synchronized void setMathContext(java.math.MathContext);
+ method public synchronized void setMathContextICU(android.icu.math.MathContext);
+ method public synchronized void setMaximumSignificantDigits(int);
+ method public synchronized void setMinimumExponentDigits(byte);
+ method public synchronized void setMinimumSignificantDigits(int);
+ method public synchronized void setMultiplier(int);
+ method public synchronized void setNegativePrefix(java.lang.String);
+ method public synchronized void setNegativeSuffix(java.lang.String);
+ method public synchronized void setPadCharacter(char);
+ method public synchronized void setPadPosition(int);
+ method public synchronized void setParseBigDecimal(boolean);
+ method public deprecated void setParseMaxDigits(int);
+ method public synchronized void setPositivePrefix(java.lang.String);
+ method public synchronized void setPositiveSuffix(java.lang.String);
+ method public synchronized void setRoundingIncrement(java.math.BigDecimal);
+ method public synchronized void setRoundingIncrement(android.icu.math.BigDecimal);
+ method public synchronized void setRoundingIncrement(double);
+ method public synchronized void setScientificNotation(boolean);
+ method public synchronized void setSecondaryGroupingSize(int);
+ method public synchronized void setSignificantDigitsUsed(boolean);
+ method public synchronized java.lang.String toLocalizedPattern();
+ method public synchronized java.lang.String toPattern();
field public static final int PAD_AFTER_PREFIX = 1; // 0x1
field public static final int PAD_AFTER_SUFFIX = 3; // 0x3
field public static final int PAD_BEFORE_PREFIX = 0; // 0x0
@@ -18787,6 +18791,8 @@
method public java.lang.String combineDateAndTime(java.lang.String, java.lang.String);
method public java.lang.String format(double, android.icu.text.RelativeDateTimeFormatter.Direction, android.icu.text.RelativeDateTimeFormatter.RelativeUnit);
method public java.lang.String format(android.icu.text.RelativeDateTimeFormatter.Direction, android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit);
+ method public java.lang.String format(double, android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit);
+ method public java.lang.String formatNumeric(double, android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit);
method public android.icu.text.DisplayContext getCapitalizationContext();
method public android.icu.text.RelativeDateTimeFormatter.Style getFormatStyle();
method public static android.icu.text.RelativeDateTimeFormatter getInstance();
@@ -18826,6 +18832,26 @@
enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction THIS;
}
+ public static final class RelativeDateTimeFormatter.RelativeDateTimeUnit extends java.lang.Enum {
+ method public static android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit valueOf(java.lang.String);
+ method public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit[] values();
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit DAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit FRIDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit HOUR;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MINUTE;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MONDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MONTH;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit QUARTER;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SATURDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SECOND;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SUNDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit THURSDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit TUESDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit WEDNESDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit WEEK;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit YEAR;
+ }
+
public static final class RelativeDateTimeFormatter.RelativeUnit extends java.lang.Enum {
method public static android.icu.text.RelativeDateTimeFormatter.RelativeUnit valueOf(java.lang.String);
method public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit[] values();
@@ -19896,6 +19922,7 @@
field public static final android.icu.util.MeasureUnit FOOT;
field public static final android.icu.util.MeasureUnit FURLONG;
field public static final android.icu.util.MeasureUnit GALLON;
+ field public static final android.icu.util.MeasureUnit GALLON_IMPERIAL;
field public static final android.icu.util.MeasureUnit GENERIC_TEMPERATURE;
field public static final android.icu.util.MeasureUnit GIGABIT;
field public static final android.icu.util.MeasureUnit GIGABYTE;
@@ -19944,11 +19971,13 @@
field public static final android.icu.util.MeasureUnit MICROSECOND;
field public static final android.icu.util.MeasureUnit MILE;
field public static final android.icu.util.MeasureUnit MILE_PER_GALLON;
+ field public static final android.icu.util.MeasureUnit MILE_PER_GALLON_IMPERIAL;
field public static final android.icu.util.MeasureUnit MILE_PER_HOUR;
field public static final android.icu.util.MeasureUnit MILE_SCANDINAVIAN;
field public static final android.icu.util.MeasureUnit MILLIAMPERE;
field public static final android.icu.util.MeasureUnit MILLIBAR;
field public static final android.icu.util.MeasureUnit MILLIGRAM;
+ field public static final android.icu.util.MeasureUnit MILLIGRAM_PER_DECILITER;
field public static final android.icu.util.MeasureUnit MILLILITER;
field public static final android.icu.util.MeasureUnit MILLIMETER;
field public static final android.icu.util.MeasureUnit MILLIMETER_OF_MERCURY;
@@ -20252,7 +20281,7 @@
field public static final int JAVA_TIME = 0; // 0x0
field public static final int MAC_OLD_TIME = 5; // 0x5
field public static final int MAC_TIME = 6; // 0x6
- field public static final int MAX_SCALE = 10; // 0xa
+ field public static final deprecated int MAX_SCALE = 10; // 0xa
field public static final int TO_MAX_VALUE = 5; // 0x5
field public static final int TO_MIN_VALUE = 4; // 0x4
field public static final int UNITS_VALUE = 0; // 0x0
diff --git a/api/test-current.txt b/api/test-current.txt
index 93c9768..15598db 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -16704,6 +16704,7 @@
field public static final java.lang.String ABBR_UTC_TZ = "ZZZZ";
field public static final java.lang.String ABBR_WEEKDAY = "E";
field public static final int AM_PM_FIELD = 14; // 0xe
+ field public static final int AM_PM_MIDNIGHT_NOON_FIELD = 35; // 0x23
field public static final int DATE_FIELD = 3; // 0x3
field public static final java.lang.String DAY = "d";
field public static final int DAY_OF_WEEK_FIELD = 9; // 0x9
@@ -16713,6 +16714,7 @@
field public static final int DOW_LOCAL_FIELD = 19; // 0x13
field public static final int ERA_FIELD = 0; // 0x0
field public static final int EXTENDED_YEAR_FIELD = 20; // 0x14
+ field public static final int FLEXIBLE_DAY_PERIOD_FIELD = 36; // 0x24
field public static final int FRACTIONAL_SECOND_FIELD = 8; // 0x8
field public static final int FULL = 0; // 0x0
field public static final java.lang.String GENERIC_TZ = "vvvv";
@@ -16801,6 +16803,7 @@
method public int getCalendarField();
method public static android.icu.text.DateFormat.Field ofCalendarField(int);
field public static final android.icu.text.DateFormat.Field AM_PM;
+ field public static final android.icu.text.DateFormat.Field AM_PM_MIDNIGHT_NOON;
field public static final android.icu.text.DateFormat.Field DAY_OF_MONTH;
field public static final android.icu.text.DateFormat.Field DAY_OF_WEEK;
field public static final android.icu.text.DateFormat.Field DAY_OF_WEEK_IN_MONTH;
@@ -16808,6 +16811,7 @@
field public static final android.icu.text.DateFormat.Field DOW_LOCAL;
field public static final android.icu.text.DateFormat.Field ERA;
field public static final android.icu.text.DateFormat.Field EXTENDED_YEAR;
+ field public static final android.icu.text.DateFormat.Field FLEXIBLE_DAY_PERIOD;
field public static final android.icu.text.DateFormat.Field HOUR0;
field public static final android.icu.text.DateFormat.Field HOUR1;
field public static final android.icu.text.DateFormat.Field HOUR_OF_DAY0;
@@ -16979,70 +16983,70 @@
ctor public DecimalFormat(java.lang.String);
ctor public DecimalFormat(java.lang.String, android.icu.text.DecimalFormatSymbols);
ctor public DecimalFormat(java.lang.String, android.icu.text.DecimalFormatSymbols, android.icu.text.CurrencyPluralInfo, int);
- method public void applyLocalizedPattern(java.lang.String);
- method public void applyPattern(java.lang.String);
- method public boolean areSignificantDigitsUsed();
+ method public synchronized void applyLocalizedPattern(java.lang.String);
+ method public synchronized void applyPattern(java.lang.String);
+ method public synchronized boolean areSignificantDigitsUsed();
method public java.lang.StringBuffer format(double, java.lang.StringBuffer, java.text.FieldPosition);
method public java.lang.StringBuffer format(long, java.lang.StringBuffer, java.text.FieldPosition);
method public java.lang.StringBuffer format(java.math.BigInteger, java.lang.StringBuffer, java.text.FieldPosition);
method public java.lang.StringBuffer format(java.math.BigDecimal, java.lang.StringBuffer, java.text.FieldPosition);
method public java.lang.StringBuffer format(android.icu.math.BigDecimal, java.lang.StringBuffer, java.text.FieldPosition);
- method public android.icu.text.CurrencyPluralInfo getCurrencyPluralInfo();
- method public android.icu.util.Currency.CurrencyUsage getCurrencyUsage();
- method public android.icu.text.DecimalFormatSymbols getDecimalFormatSymbols();
- method public int getFormatWidth();
- method public int getGroupingSize();
- method public java.math.MathContext getMathContext();
- method public android.icu.math.MathContext getMathContextICU();
- method public int getMaximumSignificantDigits();
- method public byte getMinimumExponentDigits();
- method public int getMinimumSignificantDigits();
- method public int getMultiplier();
- method public java.lang.String getNegativePrefix();
- method public java.lang.String getNegativeSuffix();
- method public char getPadCharacter();
- method public int getPadPosition();
- method public int getParseMaxDigits();
- method public java.lang.String getPositivePrefix();
- method public java.lang.String getPositiveSuffix();
- method public java.math.BigDecimal getRoundingIncrement();
- method public int getSecondaryGroupingSize();
- method public boolean isDecimalPatternMatchRequired();
- method public boolean isDecimalSeparatorAlwaysShown();
- method public boolean isExponentSignAlwaysShown();
- method public boolean isParseBigDecimal();
- method public boolean isScientificNotation();
+ method public synchronized android.icu.text.CurrencyPluralInfo getCurrencyPluralInfo();
+ method public synchronized android.icu.util.Currency.CurrencyUsage getCurrencyUsage();
+ method public synchronized android.icu.text.DecimalFormatSymbols getDecimalFormatSymbols();
+ method public synchronized int getFormatWidth();
+ method public synchronized int getGroupingSize();
+ method public synchronized java.math.MathContext getMathContext();
+ method public synchronized android.icu.math.MathContext getMathContextICU();
+ method public synchronized int getMaximumSignificantDigits();
+ method public synchronized byte getMinimumExponentDigits();
+ method public synchronized int getMinimumSignificantDigits();
+ method public synchronized int getMultiplier();
+ method public synchronized java.lang.String getNegativePrefix();
+ method public synchronized java.lang.String getNegativeSuffix();
+ method public synchronized char getPadCharacter();
+ method public synchronized int getPadPosition();
+ method public deprecated int getParseMaxDigits();
+ method public synchronized java.lang.String getPositivePrefix();
+ method public synchronized java.lang.String getPositiveSuffix();
+ method public synchronized java.math.BigDecimal getRoundingIncrement();
+ method public synchronized int getSecondaryGroupingSize();
+ method public synchronized boolean isDecimalPatternMatchRequired();
+ method public synchronized boolean isDecimalSeparatorAlwaysShown();
+ method public synchronized boolean isExponentSignAlwaysShown();
+ method public synchronized boolean isParseBigDecimal();
+ method public synchronized boolean isScientificNotation();
method public java.lang.Number parse(java.lang.String, java.text.ParsePosition);
- method public void setCurrencyPluralInfo(android.icu.text.CurrencyPluralInfo);
- method public void setCurrencyUsage(android.icu.util.Currency.CurrencyUsage);
- method public void setDecimalFormatSymbols(android.icu.text.DecimalFormatSymbols);
- method public void setDecimalPatternMatchRequired(boolean);
- method public void setDecimalSeparatorAlwaysShown(boolean);
- method public void setExponentSignAlwaysShown(boolean);
- method public void setFormatWidth(int);
- method public void setGroupingSize(int);
- method public void setMathContext(java.math.MathContext);
- method public void setMathContextICU(android.icu.math.MathContext);
- method public void setMaximumSignificantDigits(int);
- method public void setMinimumExponentDigits(byte);
- method public void setMinimumSignificantDigits(int);
- method public void setMultiplier(int);
- method public void setNegativePrefix(java.lang.String);
- method public void setNegativeSuffix(java.lang.String);
- method public void setPadCharacter(char);
- method public void setPadPosition(int);
- method public void setParseBigDecimal(boolean);
- method public void setParseMaxDigits(int);
- method public void setPositivePrefix(java.lang.String);
- method public void setPositiveSuffix(java.lang.String);
- method public void setRoundingIncrement(java.math.BigDecimal);
- method public void setRoundingIncrement(android.icu.math.BigDecimal);
- method public void setRoundingIncrement(double);
- method public void setScientificNotation(boolean);
- method public void setSecondaryGroupingSize(int);
- method public void setSignificantDigitsUsed(boolean);
- method public java.lang.String toLocalizedPattern();
- method public java.lang.String toPattern();
+ method public synchronized void setCurrencyPluralInfo(android.icu.text.CurrencyPluralInfo);
+ method public synchronized void setCurrencyUsage(android.icu.util.Currency.CurrencyUsage);
+ method public synchronized void setDecimalFormatSymbols(android.icu.text.DecimalFormatSymbols);
+ method public synchronized void setDecimalPatternMatchRequired(boolean);
+ method public synchronized void setDecimalSeparatorAlwaysShown(boolean);
+ method public synchronized void setExponentSignAlwaysShown(boolean);
+ method public synchronized void setFormatWidth(int);
+ method public synchronized void setGroupingSize(int);
+ method public synchronized void setMathContext(java.math.MathContext);
+ method public synchronized void setMathContextICU(android.icu.math.MathContext);
+ method public synchronized void setMaximumSignificantDigits(int);
+ method public synchronized void setMinimumExponentDigits(byte);
+ method public synchronized void setMinimumSignificantDigits(int);
+ method public synchronized void setMultiplier(int);
+ method public synchronized void setNegativePrefix(java.lang.String);
+ method public synchronized void setNegativeSuffix(java.lang.String);
+ method public synchronized void setPadCharacter(char);
+ method public synchronized void setPadPosition(int);
+ method public synchronized void setParseBigDecimal(boolean);
+ method public deprecated void setParseMaxDigits(int);
+ method public synchronized void setPositivePrefix(java.lang.String);
+ method public synchronized void setPositiveSuffix(java.lang.String);
+ method public synchronized void setRoundingIncrement(java.math.BigDecimal);
+ method public synchronized void setRoundingIncrement(android.icu.math.BigDecimal);
+ method public synchronized void setRoundingIncrement(double);
+ method public synchronized void setScientificNotation(boolean);
+ method public synchronized void setSecondaryGroupingSize(int);
+ method public synchronized void setSignificantDigitsUsed(boolean);
+ method public synchronized java.lang.String toLocalizedPattern();
+ method public synchronized java.lang.String toPattern();
field public static final int PAD_AFTER_PREFIX = 1; // 0x1
field public static final int PAD_AFTER_SUFFIX = 3; // 0x3
field public static final int PAD_BEFORE_PREFIX = 0; // 0x0
@@ -17590,6 +17594,8 @@
method public java.lang.String combineDateAndTime(java.lang.String, java.lang.String);
method public java.lang.String format(double, android.icu.text.RelativeDateTimeFormatter.Direction, android.icu.text.RelativeDateTimeFormatter.RelativeUnit);
method public java.lang.String format(android.icu.text.RelativeDateTimeFormatter.Direction, android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit);
+ method public java.lang.String format(double, android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit);
+ method public java.lang.String formatNumeric(double, android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit);
method public android.icu.text.DisplayContext getCapitalizationContext();
method public android.icu.text.RelativeDateTimeFormatter.Style getFormatStyle();
method public static android.icu.text.RelativeDateTimeFormatter getInstance();
@@ -17629,6 +17635,26 @@
enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction THIS;
}
+ public static final class RelativeDateTimeFormatter.RelativeDateTimeUnit extends java.lang.Enum {
+ method public static android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit valueOf(java.lang.String);
+ method public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit[] values();
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit DAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit FRIDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit HOUR;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MINUTE;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MONDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MONTH;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit QUARTER;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SATURDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SECOND;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SUNDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit THURSDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit TUESDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit WEDNESDAY;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit WEEK;
+ enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit YEAR;
+ }
+
public static final class RelativeDateTimeFormatter.RelativeUnit extends java.lang.Enum {
method public static android.icu.text.RelativeDateTimeFormatter.RelativeUnit valueOf(java.lang.String);
method public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit[] values();
@@ -18699,6 +18725,7 @@
field public static final android.icu.util.MeasureUnit FOOT;
field public static final android.icu.util.MeasureUnit FURLONG;
field public static final android.icu.util.MeasureUnit GALLON;
+ field public static final android.icu.util.MeasureUnit GALLON_IMPERIAL;
field public static final android.icu.util.MeasureUnit GENERIC_TEMPERATURE;
field public static final android.icu.util.MeasureUnit GIGABIT;
field public static final android.icu.util.MeasureUnit GIGABYTE;
@@ -18747,11 +18774,13 @@
field public static final android.icu.util.MeasureUnit MICROSECOND;
field public static final android.icu.util.MeasureUnit MILE;
field public static final android.icu.util.MeasureUnit MILE_PER_GALLON;
+ field public static final android.icu.util.MeasureUnit MILE_PER_GALLON_IMPERIAL;
field public static final android.icu.util.MeasureUnit MILE_PER_HOUR;
field public static final android.icu.util.MeasureUnit MILE_SCANDINAVIAN;
field public static final android.icu.util.MeasureUnit MILLIAMPERE;
field public static final android.icu.util.MeasureUnit MILLIBAR;
field public static final android.icu.util.MeasureUnit MILLIGRAM;
+ field public static final android.icu.util.MeasureUnit MILLIGRAM_PER_DECILITER;
field public static final android.icu.util.MeasureUnit MILLILITER;
field public static final android.icu.util.MeasureUnit MILLIMETER;
field public static final android.icu.util.MeasureUnit MILLIMETER_OF_MERCURY;
@@ -19055,7 +19084,7 @@
field public static final int JAVA_TIME = 0; // 0x0
field public static final int MAC_OLD_TIME = 5; // 0x5
field public static final int MAC_TIME = 6; // 0x6
- field public static final int MAX_SCALE = 10; // 0xa
+ field public static final deprecated int MAX_SCALE = 10; // 0xa
field public static final int TO_MAX_VALUE = 5; // 0x5
field public static final int TO_MIN_VALUE = 4; // 0x4
field public static final int UNITS_VALUE = 0; // 0x0
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index dfd5996..44c2667 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -415,7 +415,8 @@
gatt = mBluetoothManager.getBluetoothGatt();
} catch (RemoteException e) {
Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
- throw new IllegalStateException("Failed to get Bluetooth");
+ postStartSetFailure(handler, callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
+ return;
}
IAdvertisingSetCallback wrapped = wrap(callback, handler);
@@ -429,7 +430,8 @@
periodicData, duration, maxExtendedAdvertisingEvents, wrapped);
} catch (RemoteException e) {
Log.e(TAG, "Failed to start advertising set - ", e);
- throw new IllegalStateException("Failed to start advertising set");
+ postStartSetFailure(handler, callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
+ return;
}
}
@@ -453,8 +455,7 @@
gatt.stopAdvertisingSet(wrapped);
} catch (RemoteException e) {
Log.e(TAG, "Failed to stop advertising - ", e);
- throw new IllegalStateException("Failed to stop advertising");
- }
+ }
}
/**
@@ -648,6 +649,16 @@
};
}
+ private void postStartSetFailure(Handler handler, final AdvertisingSetCallback callback,
+ final int error) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onAdvertisingSetStarted(null, 0, error);
+ }
+ });
+ }
+
private void postStartFailure(final AdvertiseCallback callback, final int error) {
mHandler.post(new Runnable() {
@Override
diff --git a/core/java/android/net/ITetheringStatsProvider.aidl b/core/java/android/net/ITetheringStatsProvider.aidl
index 769086d..1aeabc1 100644
--- a/core/java/android/net/ITetheringStatsProvider.aidl
+++ b/core/java/android/net/ITetheringStatsProvider.aidl
@@ -19,7 +19,7 @@
import android.net.NetworkStats;
/**
- * Interface that allows NetworkManagementService to query for tethering statistics.
+ * Interface for NetworkManagementService to query tethering statistics and set data limits.
*
* TODO: this does not really need to be an interface since Tethering runs in the same process
* as NetworkManagementService. Consider refactoring Tethering to use direct access to
@@ -29,5 +29,14 @@
* @hide
*/
interface ITetheringStatsProvider {
+ // Returns cumulative statistics for all tethering sessions since boot, on all upstreams.
NetworkStats getTetherStats();
+
+ // Sets the interface quota for the specified upstream interface. This is defined as the number
+ // of bytes, starting from zero and counting from now, after which data should stop being
+ // forwarded to/from the specified upstream. A value of QUOTA_UNLIMITED means there is no limit.
+ void setInterfaceQuota(String iface, long quotaBytes);
+
+ // Indicates that no data usage limit is set.
+ const int QUOTA_UNLIMITED = -1;
}
diff --git a/core/java/android/net/IpPrefix.java b/core/java/android/net/IpPrefix.java
index 6b4f2d5..6e2654e 100644
--- a/core/java/android/net/IpPrefix.java
+++ b/core/java/android/net/IpPrefix.java
@@ -20,6 +20,8 @@
import android.os.Parcelable;
import android.util.Pair;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
@@ -185,6 +187,20 @@
}
/**
+ * @hide
+ */
+ public boolean isIPv6() {
+ return getAddress() instanceof Inet6Address;
+ }
+
+ /**
+ * @hide
+ */
+ public boolean isIPv4() {
+ return getAddress() instanceof Inet4Address;
+ }
+
+ /**
* Returns a string representation of this {@code IpPrefix}.
*
* @return a string such as {@code "192.0.2.0/24"} or {@code "2001:db8:1:2::/64"}.
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index 62de991..bcfe938 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -76,7 +76,7 @@
* RFC 6724 section 3.2.
* @hide
*/
- static int scopeForUnicastAddress(InetAddress addr) {
+ private static int scopeForUnicastAddress(InetAddress addr) {
if (addr.isAnyLocalAddress()) {
return RT_SCOPE_HOST;
}
@@ -101,7 +101,7 @@
* Per RFC 4193 section 8, fc00::/7 identifies these addresses.
*/
private boolean isIPv6ULA() {
- if (address instanceof Inet6Address) {
+ if (isIPv6()) {
byte[] bytes = address.getAddress();
return ((bytes[0] & (byte)0xfe) == (byte)0xfc);
}
@@ -109,13 +109,29 @@
}
/**
+ * @return true if the address is IPv6.
+ * @hide
+ */
+ public boolean isIPv6() {
+ return address instanceof Inet6Address;
+ }
+
+ /**
+ * @return true if the address is IPv4 or is a mapped IPv4 address.
+ * @hide
+ */
+ public boolean isIPv4() {
+ return address instanceof Inet4Address;
+ }
+
+ /**
* Utility function for the constructors.
*/
private void init(InetAddress address, int prefixLength, int flags, int scope) {
if (address == null ||
address.isMulticastAddress() ||
prefixLength < 0 ||
- ((address instanceof Inet4Address) && prefixLength > 32) ||
+ (address instanceof Inet4Address && prefixLength > 32) ||
(prefixLength > 128)) {
throw new IllegalArgumentException("Bad LinkAddress params " + address +
"/" + prefixLength);
@@ -184,6 +200,7 @@
*/
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".
Pair<InetAddress, Integer> ipAndMask = NetworkUtils.parseIpAndMask(address);
init(ipAndMask.first, ipAndMask.second, flags, scope);
}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 0b92893..4bb8844 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -770,7 +770,6 @@
StringJoiner joiner = new StringJoiner(", ");
- // TODO: consider only enforcing that capabilities are not removed, allowing addition.
// Ignore NOT_METERED being added or removed as it is effectively dynamic. http://b/63326103
// TODO: properly support NOT_METERED as a mutable and requestable capability.
final long mask = ~MUTABLE_CAPABILITIES & ~(1 << NET_CAPABILITY_NOT_METERED);
diff --git a/core/java/com/android/internal/net/OWNERS b/core/java/com/android/internal/net/OWNERS
new file mode 100644
index 0000000..7cb32ff
--- /dev/null
+++ b/core/java/com/android/internal/net/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+
+ek@google.com
+hugobenichi@google.com
+jsharkey@google.com
+lorenzo@google.com
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 24e1b33..bc27663 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -41,6 +41,8 @@
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
+import android.system.StructCapUserData;
+import android.system.StructCapUserHeader;
import android.text.Hyphenator;
import android.util.EventLog;
import android.util.Log;
@@ -80,7 +82,6 @@
private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload";
private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
- private static final String PROPERTY_RUNNING_IN_CONTAINER = "ro.boot.container";
private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020;
private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030;
@@ -567,12 +568,20 @@
OsConstants.CAP_SYS_RESOURCE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG,
- OsConstants.CAP_WAKE_ALARM
+ OsConstants.CAP_WAKE_ALARM,
+ OsConstants.CAP_BLOCK_SUSPEND
);
- /* Containers run without this capability, so avoid setting it in that case */
- if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
- capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
+ /* Containers run without some capabilities, so drop any caps that are not available. */
+ StructCapUserHeader header = new StructCapUserHeader(
+ OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
+ StructCapUserData[] data;
+ try {
+ data = Os.capget(header);
+ } catch (ErrnoException ex) {
+ throw new RuntimeException("Failed to capget()", ex);
}
+ capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);
+
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
index 0c23797..40d49b7 100644
--- a/core/jni/android_os_HwBlob.cpp
+++ b/core/jni/android_os_HwBlob.cpp
@@ -83,12 +83,6 @@
mSize(size),
mOwnsBuffer(true),
mHandle(0) {
- jclass clazz = env->GetObjectClass(thiz);
- CHECK(clazz != NULL);
-
- mClass = (jclass)env->NewGlobalRef(clazz);
- mObject = env->NewWeakGlobalRef(thiz);
-
if (size > 0) {
mBuffer = malloc(size);
}
@@ -99,14 +93,6 @@
free(mBuffer);
mBuffer = nullptr;
}
-
- JNIEnv *env = AndroidRuntime::getJNIEnv();
-
- env->DeleteWeakGlobalRef(mObject);
- mObject = NULL;
-
- env->DeleteGlobalRef(mClass);
- mClass = NULL;
}
void JHwBlob::setTo(const void *ptr, size_t handle) {
diff --git a/core/jni/android_os_HwBlob.h b/core/jni/android_os_HwBlob.h
index 0920488..39393cb 100644
--- a/core/jni/android_os_HwBlob.h
+++ b/core/jni/android_os_HwBlob.h
@@ -70,9 +70,6 @@
sp<JHwBlob> mBlob;
};
- jclass mClass;
- jobject mObject;
-
void *mBuffer;
size_t mSize;
bool mOwnsBuffer;
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index b412b6a..9494fb8 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -166,10 +166,6 @@
mOwnsParcel(false),
mTransactCallback(nullptr),
mWasSent(false) {
- jclass clazz = env->GetObjectClass(thiz);
- CHECK(clazz != NULL);
-
- mObject = env->NewWeakGlobalRef(thiz);
}
JHwParcel::~JHwParcel() {
@@ -178,9 +174,6 @@
mStorage.release(env);
setParcel(NULL, false /* assumeOwnership */);
-
- env->DeleteWeakGlobalRef(mObject);
- mObject = NULL;
}
hardware::Parcel *JHwParcel::getParcel() {
diff --git a/core/jni/android_os_HwParcel.h b/core/jni/android_os_HwParcel.h
index f6e6100..2c26993 100644
--- a/core/jni/android_os_HwParcel.h
+++ b/core/jni/android_os_HwParcel.h
@@ -53,8 +53,6 @@
virtual ~JHwParcel();
private:
- jobject mObject;
-
hardware::Parcel *mParcel;
bool mOwnsParcel;
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index dba8194..914688e 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -674,6 +674,22 @@
}
return pid;
}
+
+static uint64_t GetEffectiveCapabilityMask(JNIEnv* env) {
+ __user_cap_header_struct capheader;
+ memset(&capheader, 0, sizeof(capheader));
+ capheader.version = _LINUX_CAPABILITY_VERSION_3;
+ capheader.pid = 0;
+
+ __user_cap_data_struct capdata[2];
+ if (capget(&capheader, &capdata[0]) == -1) {
+ ALOGE("capget failed: %s", strerror(errno));
+ RuntimeAbort(env, __LINE__, "capget failed");
+ }
+
+ return capdata[0].effective |
+ (static_cast<uint64_t>(capdata[1].effective) << 32);
+}
} // anonymous namespace
namespace android {
@@ -724,6 +740,10 @@
capabilities |= (1LL << CAP_BLOCK_SUSPEND);
}
+ // Containers run without some capabilities, so drop any caps that are not
+ // available.
+ capabilities &= GetEffectiveCapabilityMask(env);
+
return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
rlimits, capabilities, capabilities, mount_external, se_info,
se_name, false, fdsToClose, fdsToIgnore, instructionSet, appDataDir);
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index af78669..78ffb5b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2783,4 +2783,8 @@
<!-- Package name of the default cell broadcast receiver -->
<string name="config_defaultCellBroadcastReceiverPkg" translatable="false">com.android.cellbroadcastreceiver</string>
+ <!-- When true, indicates that the vendor's IMS implementation requires a workaround when
+ sending a request to enable or disable the camera while the video session is also
+ paused. -->
+ <bool name="config_useVideoPauseWorkaround">false</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c53093f..4bf5043 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2795,4 +2795,5 @@
<java-symbol type="string" name="etws_primary_default_message_test" />
<java-symbol type="string" name="etws_primary_default_message_others" />
+ <java-symbol type="bool" name="config_useVideoPauseWorkaround" />
</resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index c1a3f86..d556b64 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -467,6 +467,12 @@
loadingContent.layout(0, 0, loadingContent.getMeasuredWidth(),
loadingContent.getMeasuredHeight());
+ // To create a bitmap, height & width should be larger than 0
+ if (mPageContentHeight <= 0 || mPageContentWidth <= 0) {
+ Log.w(LOG_TAG, "Unable to create bitmap, height or width smaller than 0!");
+ return;
+ }
+
Bitmap loadingBitmap = Bitmap.createBitmap(mPageContentWidth, mPageContentHeight,
Bitmap.Config.ARGB_8888);
loadingContent.draw(new Canvas(loadingBitmap));
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 8972802..0babbc8 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4702,11 +4702,15 @@
*/
private void updateCapabilities(
int oldScore, NetworkAgentInfo nai, NetworkCapabilities networkCapabilities) {
- // Sanity check: a NetworkAgent should not change its static capabilities or parameters.
- if (nai.everConnected) {
+ // Once a NetworkAgent is connected, complain if some immutable capabilities are removed.
+ if (nai.everConnected &&
+ !nai.networkCapabilities.satisfiedByNetworkCapabilities(networkCapabilities)) {
+ // TODO: consider not complaining when a network agent degrade its capabilities if this
+ // does not cause any request (that is not a listen) currently matching that agent to
+ // stop being matched by the updated agent.
String diff = nai.networkCapabilities.describeImmutableDifferences(networkCapabilities);
if (!TextUtils.isEmpty(diff)) {
- Slog.wtf(TAG, "BUG: " + nai + " changed immutable capabilities:" + diff);
+ Slog.wtf(TAG, "BUG: " + nai + " lost immutable capabilities:" + diff);
}
}
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index ab7dacc..3056831 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -142,6 +142,17 @@
}
mCurrent--;
}
+
+ @Override
+ public String toString() {
+ return new StringBuilder()
+ .append("{mCurrent=")
+ .append(mCurrent)
+ .append(", mMax=")
+ .append(mMax)
+ .append("}")
+ .toString();
+ }
}
private static final class UserQuotaTracker {
@@ -159,6 +170,19 @@
public final ResourceTracker socket = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS);
public final ResourceTracker transform = new ResourceTracker(MAX_NUM_TRANSFORMS);
public final ResourceTracker spi = new ResourceTracker(MAX_NUM_SPIS);
+
+ @Override
+ public String toString() {
+ return new StringBuilder()
+ .append("{socket=")
+ .append(socket)
+ .append(", transform=")
+ .append(transform)
+ .append(", spi=")
+ .append(spi)
+ .append("}")
+ .toString();
+ }
}
private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
@@ -172,6 +196,11 @@
}
return r;
}
+
+ @Override
+ public String toString() {
+ return mUserRecords.toString();
+ }
}
private final UserQuotaTracker mUserQuotaTracker = new UserQuotaTracker();
@@ -909,6 +938,8 @@
pw.println("NetdNativeService Connection: " + (isNetdAlive() ? "alive" : "dead"));
pw.println();
+ pw.println("mUserQuotaTracker:");
+ pw.println(mUserQuotaTracker);
pw.println("mTransformRecords:");
pw.println(mTransformRecords);
pw.println("mUdpSocketRecords:");
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 097202b..3d638be 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1538,6 +1538,17 @@
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
+
+ synchronized (mTetheringStatsProviders) {
+ for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
+ try {
+ provider.setInterfaceQuota(iface, quotaBytes);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Problem setting tethering data limit on provider " +
+ mTetheringStatsProviders.get(provider) + ": " + e);
+ }
+ }
+ }
}
}
@@ -1564,6 +1575,17 @@
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
+
+ synchronized (mTetheringStatsProviders) {
+ for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
+ try {
+ provider.setInterfaceQuota(iface, ITetheringStatsProvider.QUOTA_UNLIMITED);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Problem removing tethering data limit on provider " +
+ mTetheringStatsProviders.get(provider) + ": " + e);
+ }
+ }
+ }
}
}
@@ -1823,6 +1845,11 @@
}
return stats;
}
+
+ @Override
+ public void setInterfaceQuota(String iface, long quotaBytes) {
+ // Do nothing. netd is already informed of quota changes in setInterfaceQuota.
+ }
}
@Override
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
index 1a5ff77..55e290a 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
@@ -46,7 +46,6 @@
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
@@ -58,8 +57,6 @@
public class OffloadController {
private static final String TAG = OffloadController.class.getSimpleName();
- private static final int STATS_FETCH_TIMEOUT_MS = 1000;
-
private final Handler mHandler;
private final OffloadHardwareInterface mHwInterface;
private final ContentResolver mContentResolver;
@@ -76,9 +73,17 @@
private Set<String> mLastLocalPrefixStrs;
// Maps upstream interface names to offloaded traffic statistics.
+ // Always contains the latest value received from the hardware for each interface, regardless of
+ // whether offload is currently running on that interface.
private HashMap<String, OffloadHardwareInterface.ForwardedStats>
mForwardedStats = new HashMap<>();
+ // Maps upstream interface names to interface quotas.
+ // Always contains the latest value received from the framework for each interface, regardless
+ // of whether offload is currently running (or is even supported) on that interface. Only
+ // includes upstream interfaces that have a quota set.
+ private HashMap<String, Long> mInterfaceQuotas = new HashMap<>();
+
public OffloadController(Handler h, OffloadHardwareInterface hwi,
ContentResolver contentResolver, INetworkManagementService nms, SharedLog log) {
mHandler = h;
@@ -177,36 +182,38 @@
@Override
public NetworkStats getTetherStats() {
NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
- CountDownLatch latch = new CountDownLatch(1);
- mHandler.post(() -> {
- try {
- NetworkStats.Entry entry = new NetworkStats.Entry();
- entry.set = SET_DEFAULT;
- entry.tag = TAG_NONE;
- entry.uid = UID_TETHERING;
+ // We can't just post to mHandler because we are mostly (but not always) called by
+ // NetworkStatsService#performPollLocked, which is (currently) on the same thread as us.
+ mHandler.runWithScissors(() -> {
+ NetworkStats.Entry entry = new NetworkStats.Entry();
+ entry.set = SET_DEFAULT;
+ entry.tag = TAG_NONE;
+ entry.uid = UID_TETHERING;
- updateStatsForCurrentUpstream();
+ updateStatsForCurrentUpstream();
- for (String iface : mForwardedStats.keySet()) {
- entry.iface = iface;
- entry.rxBytes = mForwardedStats.get(iface).rxBytes;
- entry.txBytes = mForwardedStats.get(iface).txBytes;
- stats.addValues(entry);
- }
- } finally {
- latch.countDown();
+ for (String iface : mForwardedStats.keySet()) {
+ entry.iface = iface;
+ entry.rxBytes = mForwardedStats.get(iface).rxBytes;
+ entry.txBytes = mForwardedStats.get(iface).txBytes;
+ stats.addValues(entry);
}
- });
-
- try {
- latch.await(STATS_FETCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- mLog.e("Tethering stats fetch timed out after " + STATS_FETCH_TIMEOUT_MS + "ms");
- }
+ }, 0);
return stats;
}
+
+ public void setInterfaceQuota(String iface, long quotaBytes) {
+ mHandler.post(() -> {
+ if (quotaBytes == ITetheringStatsProvider.QUOTA_UNLIMITED) {
+ mInterfaceQuotas.remove(iface);
+ } else {
+ mInterfaceQuotas.put(iface, quotaBytes);
+ }
+ maybeUpdateDataLimit(iface);
+ });
+ }
}
private void maybeUpdateStats(String iface) {
@@ -220,6 +227,22 @@
mForwardedStats.get(iface).add(mHwInterface.getForwardedStats(iface));
}
+ private boolean maybeUpdateDataLimit(String iface) {
+ // setDataLimit may only be called while offload is occuring on this upstream.
+ if (!started() ||
+ mUpstreamLinkProperties == null ||
+ !TextUtils.equals(iface, mUpstreamLinkProperties.getInterfaceName())) {
+ return true;
+ }
+
+ Long limit = mInterfaceQuotas.get(iface);
+ if (limit == null) {
+ limit = Long.MAX_VALUE;
+ }
+
+ return mHwInterface.setDataLimit(iface, limit);
+ }
+
private void updateStatsForCurrentUpstream() {
if (mUpstreamLinkProperties != null) {
maybeUpdateStats(mUpstreamLinkProperties.getInterfaceName());
@@ -309,8 +332,21 @@
}
}
- return mHwInterface.setUpstreamParameters(
+ boolean success = mHwInterface.setUpstreamParameters(
iface, v4addr, v4gateway, (v6gateways.isEmpty() ? null : v6gateways));
+
+ if (!success) {
+ return success;
+ }
+
+ // Data limits can only be set once offload is running on the upstream.
+ success = maybeUpdateDataLimit(iface);
+ if (!success) {
+ mLog.log("Setting data limit for " + iface + " failed, disabling offload.");
+ stop();
+ }
+
+ return success;
}
private boolean computeAndPushLocalPrefixes() {
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
index 4df566f..86ff0a6 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -188,6 +188,27 @@
return results.success;
}
+ public boolean setDataLimit(String iface, long limit) {
+
+ final String logmsg = String.format("setDataLimit(%s, %d)", iface, limit);
+
+ final CbResults results = new CbResults();
+ try {
+ mOffloadControl.setDataLimit(
+ iface, limit,
+ (boolean success, String errMsg) -> {
+ results.success = success;
+ results.errMsg = errMsg;
+ });
+ } catch (RemoteException e) {
+ record(logmsg, e);
+ return false;
+ }
+
+ record(logmsg, results);
+ return results.success;
+ }
+
public boolean setUpstreamParameters(
String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) {
iface = (iface != null) ? iface : NO_INTERFACE_NAME;
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 7401dda..79064bf 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -100,6 +100,7 @@
private static final String SESSION_ADD_CS_ADAPTER = "CS.aCSA";
private static final String SESSION_REMOVE_CS_ADAPTER = "CS.rCSA";
private static final String SESSION_CREATE_CONN = "CS.crCo";
+ private static final String SESSION_CREATE_CONN_COMPLETE = "CS.crCoC";
private static final String SESSION_CREATE_CONN_FAILED = "CS.crCoF";
private static final String SESSION_ABORT = "CS.ab";
private static final String SESSION_ANSWER = "CS.an";
@@ -152,6 +153,7 @@
private static final int MSG_ON_START_RTT = 26;
private static final int MSG_ON_STOP_RTT = 27;
private static final int MSG_RTT_UPGRADE_RESPONSE = 28;
+ private static final int MSG_CREATE_CONNECTION_COMPLETE = 29;
private static Connection sNullConnection;
@@ -221,6 +223,19 @@
}
@Override
+ public void createConnectionComplete(String id, Session.Info sessionInfo) {
+ Log.startSession(sessionInfo, SESSION_CREATE_CONN_COMPLETE);
+ try {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = id;
+ args.arg2 = Log.createSubsession();
+ mHandler.obtainMessage(MSG_CREATE_CONNECTION_COMPLETE, args).sendToTarget();
+ } finally {
+ Log.endSession();
+ }
+ }
+
+ @Override
public void createConnectionFailed(
PhoneAccountHandle connectionManagerPhoneAccount,
String callId,
@@ -630,6 +645,33 @@
}
break;
}
+ case MSG_CREATE_CONNECTION_COMPLETE: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ Log.continueSession((Session) args.arg2,
+ SESSION_HANDLER + SESSION_CREATE_CONN_COMPLETE);
+ try {
+ final String id = (String) args.arg1;
+ if (!mAreAccountsInitialized) {
+ Log.d(this, "Enqueueing pre-init request %s", id);
+ mPreInitializationConnectionRequests.add(
+ new android.telecom.Logging.Runnable(
+ SESSION_HANDLER + SESSION_CREATE_CONN_COMPLETE
+ + ".pICR",
+ null /*lock*/) {
+ @Override
+ public void loggedRun() {
+ notifyCreateConnectionComplete(id);
+ }
+ }.prepare());
+ } else {
+ notifyCreateConnectionComplete(id);
+ }
+ } finally {
+ args.recycle();
+ Log.endSession();
+ }
+ break;
+ }
case MSG_CREATE_CONNECTION_FAILED: {
SomeArgs args = (SomeArgs) msg.obj;
Log.continueSession((Session) args.arg3, SESSION_HANDLER +
@@ -1373,6 +1415,17 @@
}
}
+ /**
+ * Called by Telecom when the creation of a new Connection has completed and it is now added
+ * to Telecom.
+ * @param callId The ID of the connection.
+ */
+ private void notifyCreateConnectionComplete(final String callId) {
+ Log.i(this, "notifyCreateConnectionComplete %s", callId);
+ onCreateConnectionComplete(findConnectionForAction(callId,
+ "notifyCreateConnectionComplete"));
+ }
+
private void abort(String callId) {
Log.d(this, "abort %s", callId);
findConnectionForAction(callId, "abort").onAbort();
@@ -1837,6 +1890,18 @@
}
/**
+ * Called after the {@link Connection} returned by
+ * {@link #onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}
+ * or {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)} has been
+ * added to the {@link ConnectionService} and sent to Telecom.
+ *
+ * @param connection the {@link Connection}.
+ * @hide
+ */
+ public void onCreateConnectionComplete(Connection connection) {
+ }
+
+ /**
* Called by Telecom to inform the {@link ConnectionService} that its request to create a new
* incoming {@link Connection} was denied.
* <p>
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index e6b567e..dcf5c27 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -83,6 +83,13 @@
*/
public static final String REASON_WIFI_ON_BUT_WFC_OFF = "REASON_WIFI_ON_BUT_WFC_OFF";
+ /**
+ * Reason code (returned via {@link #getReason()}), which indicates that the video telephony
+ * call was disconnected because IMS access is blocked.
+ * @hide
+ */
+ public static final String REASON_IMS_ACCESS_BLOCKED = "REASON_IMS_ACCESS_BLOCKED";
+
private int mDisconnectCode;
private CharSequence mDisconnectLabel;
private CharSequence mDisconnectDescription;
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index c631d08..e428286 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -47,6 +47,8 @@
boolean isUnknown,
in Session.Info sessionInfo);
+ void createConnectionComplete(String callId, in Session.Info sessionInfo);
+
void createConnectionFailed(in PhoneAccountHandle connectionManagerPhoneAccount, String callId,
in ConnectionRequest request, boolean isIncoming, in Session.Info sessionInfo);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 5fb83ab..e448fb2 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -795,34 +795,57 @@
return rtString;
}
+ /**
+ * Convert RIL Service State to String
+ *
+ * @param serviceState
+ * @return String representation of the ServiceState
+ *
+ * @hide
+ */
+ public static String rilServiceStateToString(int serviceState) {
+ switch(serviceState) {
+ case STATE_IN_SERVICE:
+ return "IN_SERVICE";
+ case STATE_OUT_OF_SERVICE:
+ return "OUT_OF_SERVICE";
+ case STATE_EMERGENCY_ONLY:
+ return "EMERGENCY_ONLY";
+ case STATE_POWER_OFF:
+ return "POWER_OFF";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
@Override
public String toString() {
- String radioTechnology = rilRadioTechnologyToString(mRilVoiceRadioTechnology);
- String dataRadioTechnology = rilRadioTechnologyToString(mRilDataRadioTechnology);
-
- return (mVoiceRegState + " " + mDataRegState
- + " "
- + "voice " + getRoamingLogString(mVoiceRoamingType)
- + " "
- + "data " + getRoamingLogString(mDataRoamingType)
- + " " + mVoiceOperatorAlphaLong
- + " " + mVoiceOperatorAlphaShort
- + " " + mVoiceOperatorNumeric
- + " " + mDataOperatorAlphaLong
- + " " + mDataOperatorAlphaShort
- + " " + mDataOperatorNumeric
- + " " + (mIsManualNetworkSelection ? "(manual)" : "")
- + " " + radioTechnology
- + " " + dataRadioTechnology
- + " " + (mCssIndicator ? "CSS supported" : "CSS not supported")
- + " " + mNetworkId
- + " " + mSystemId
- + " RoamInd=" + mCdmaRoamingIndicator
- + " DefRoamInd=" + mCdmaDefaultRoamingIndicator
- + " EmergOnly=" + mIsEmergencyOnly
- + " IsDataRoamingFromRegistration=" + mIsDataRoamingFromRegistration
- + " IsUsingCarrierAggregation=" + mIsUsingCarrierAggregation
- + " mLteEarfcnRsrpBoost=" + mLteEarfcnRsrpBoost);
+ return new StringBuilder().append("{mVoiceRegState=").append(mVoiceRegState)
+ .append("(" + rilServiceStateToString(mVoiceRegState) + ")")
+ .append(", mDataRegState=").append(mDataRegState)
+ .append("(" + rilServiceStateToString(mDataRegState) + ")")
+ .append(", mVoiceRoamingType=").append(getRoamingLogString(mVoiceRoamingType))
+ .append(", mDataRoamingType=").append(getRoamingLogString(mDataRoamingType))
+ .append(", mVoiceOperatorAlphaLong=").append(mVoiceOperatorAlphaLong)
+ .append(", mVoiceOperatorAlphaShort=").append(mVoiceOperatorAlphaShort)
+ .append(", mDataOperatorAlphaLong=").append(mDataOperatorAlphaLong)
+ .append(", mDataOperatorAlphaShort=").append(mDataOperatorAlphaShort)
+ .append(", isManualNetworkSelection=").append(mIsManualNetworkSelection)
+ .append(mIsManualNetworkSelection ? "(manual)" : "(automatic)")
+ .append(", mRilVoiceRadioTechnology=").append(mRilVoiceRadioTechnology)
+ .append("(" + rilRadioTechnologyToString(mRilVoiceRadioTechnology) + ")")
+ .append(", mRilDataRadioTechnology=").append(mRilDataRadioTechnology)
+ .append("(" + rilRadioTechnologyToString(mRilDataRadioTechnology) + ")")
+ .append(", mCssIndicator=").append(mCssIndicator ? "supported" : "unsupported")
+ .append(", mNetworkId=").append(mNetworkId)
+ .append(", mSystemId=").append(mSystemId)
+ .append(", mCdmaRoamingIndicator=").append(mCdmaRoamingIndicator)
+ .append(", mCdmaDefaultRoamingIndicator=").append(mCdmaDefaultRoamingIndicator)
+ .append(", mIsEmergencyOnly=").append(mIsEmergencyOnly)
+ .append(", mIsDataRoamingFromRegistration=").append(mIsDataRoamingFromRegistration)
+ .append(", mIsUsingCarrierAggregation=").append(mIsUsingCarrierAggregation)
+ .append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
+ .append("}").toString();
}
private void setNullState(int state) {
diff --git a/core/tests/coretests/src/android/net/IpPrefixTest.java b/tests/net/java/android/net/IpPrefixTest.java
similarity index 93%
rename from core/tests/coretests/src/android/net/IpPrefixTest.java
rename to tests/net/java/android/net/IpPrefixTest.java
index 4f2387d..b5b2c07 100644
--- a/core/tests/coretests/src/android/net/IpPrefixTest.java
+++ b/tests/net/java/android/net/IpPrefixTest.java
@@ -16,18 +16,27 @@
package android.net;
-import android.net.IpPrefix;
-import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
-import java.net.InetAddress;
-import java.util.Random;
-import junit.framework.TestCase;
-
-import static android.test.MoreAsserts.assertNotEqual;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
-public class IpPrefixTest extends TestCase {
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import java.net.InetAddress;
+import java.util.Random;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IpPrefixTest {
private static InetAddress Address(String addr) {
return InetAddress.parseNumericAddress(addr);
@@ -42,7 +51,7 @@
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xa0
};
- @SmallTest
+ @Test
public void testConstructor() {
IpPrefix p;
try {
@@ -103,6 +112,7 @@
} catch(IllegalArgumentException expected) {}
}
+ @Test
public void testTruncation() {
IpPrefix p;
@@ -170,7 +180,7 @@
assertFalse(o2.equals(o1));
}
- @SmallTest
+ @Test
public void testEquals() {
IpPrefix p1, p2;
@@ -212,7 +222,7 @@
assertAreNotEqual(p1, p2);
}
- @SmallTest
+ @Test
public void testContains() {
IpPrefix p = new IpPrefix("2001:db8:f00::ace:d00d/127");
assertTrue(p.contains(Address("2001:db8:f00::ace:d00c")));
@@ -240,7 +250,7 @@
assertFalse(ipv4Default.contains(Address("2001:db8::f00")));
}
- @SmallTest
+ @Test
public void testHashCode() {
IpPrefix p = new IpPrefix(new byte[4], 0);
Random random = new Random();
@@ -261,12 +271,12 @@
assertEquals(p.hashCode(), oldP.hashCode());
}
if (p.hashCode() != oldP.hashCode()) {
- assertNotEqual(p, oldP);
+ assertNotEquals(p, oldP);
}
}
}
- @SmallTest
+ @Test
public void testHashCodeIsNotConstant() {
IpPrefix[] prefixes = {
new IpPrefix("2001:db8:f00::ace:d00d/127"),
@@ -276,12 +286,12 @@
};
for (int i = 0; i < prefixes.length; i++) {
for (int j = i + 1; j < prefixes.length; j++) {
- assertNotEqual(prefixes[i].hashCode(), prefixes[j].hashCode());
+ assertNotEquals(prefixes[i].hashCode(), prefixes[j].hashCode());
}
}
}
- @SmallTest
+ @Test
public void testMappedAddressesAreBroken() {
// 192.0.2.0/24 != ::ffff:c000:0204/120, but because we use InetAddress,
// we are unable to comprehend that.
@@ -318,13 +328,16 @@
assertEquals(p, p2);
}
+ @Test
public void testParceling() {
IpPrefix p;
p = new IpPrefix("2001:4860:db8::/64");
assertParcelingIsLossless(p);
+ assertTrue(p.isIPv6());
p = new IpPrefix("192.0.2.0/25");
assertParcelingIsLossless(p);
+ assertTrue(p.isIPv4());
}
}
diff --git a/core/tests/coretests/src/android/net/LinkAddressTest.java b/tests/net/java/android/net/LinkAddressTest.java
similarity index 91%
rename from core/tests/coretests/src/android/net/LinkAddressTest.java
rename to tests/net/java/android/net/LinkAddressTest.java
index adf8d95..c1ad946 100644
--- a/core/tests/coretests/src/android/net/LinkAddressTest.java
+++ b/tests/net/java/android/net/LinkAddressTest.java
@@ -16,6 +16,23 @@
package android.net;
+import static android.system.OsConstants.IFA_F_DADFAILED;
+import static android.system.OsConstants.IFA_F_DEPRECATED;
+import static android.system.OsConstants.IFA_F_OPTIMISTIC;
+import static android.system.OsConstants.IFA_F_PERMANENT;
+import static android.system.OsConstants.IFA_F_TEMPORARY;
+import static android.system.OsConstants.IFA_F_TENTATIVE;
+import static android.system.OsConstants.RT_SCOPE_HOST;
+import static android.system.OsConstants.RT_SCOPE_LINK;
+import static android.system.OsConstants.RT_SCOPE_SITE;
+import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
@@ -27,44 +44,35 @@
import java.util.Comparator;
import java.util.List;
-import android.net.LinkAddress;
import android.os.Parcel;
-import android.test.AndroidTestCase;
-import static android.test.MoreAsserts.assertNotEqual;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
-import static android.system.OsConstants.IFA_F_DADFAILED;
-import static android.system.OsConstants.IFA_F_DEPRECATED;
-import static android.system.OsConstants.IFA_F_OPTIMISTIC;
-import static android.system.OsConstants.IFA_F_PERMANENT;
-import static android.system.OsConstants.IFA_F_TEMPORARY;
-import static android.system.OsConstants.IFA_F_TENTATIVE;
-import static android.system.OsConstants.RT_SCOPE_HOST;
-import static android.system.OsConstants.RT_SCOPE_LINK;
-import static android.system.OsConstants.RT_SCOPE_SITE;
-import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
+import org.junit.runner.RunWith;
+import org.junit.Test;
-/**
- * Tests for {@link LinkAddress}.
- */
-public class LinkAddressTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class LinkAddressTest {
private static final String V4 = "192.0.2.1";
private static final String V6 = "2001:db8::1";
private static final InetAddress V4_ADDRESS = NetworkUtils.numericToInetAddress(V4);
private static final InetAddress V6_ADDRESS = NetworkUtils.numericToInetAddress(V6);
+ @Test
public void testConstants() {
// RT_SCOPE_UNIVERSE = 0, but all the other constants should be nonzero.
- assertNotEqual(0, RT_SCOPE_HOST);
- assertNotEqual(0, RT_SCOPE_LINK);
- assertNotEqual(0, RT_SCOPE_SITE);
+ assertNotEquals(0, RT_SCOPE_HOST);
+ assertNotEquals(0, RT_SCOPE_LINK);
+ assertNotEquals(0, RT_SCOPE_SITE);
- assertNotEqual(0, IFA_F_DEPRECATED);
- assertNotEqual(0, IFA_F_PERMANENT);
- assertNotEqual(0, IFA_F_TENTATIVE);
+ assertNotEquals(0, IFA_F_DEPRECATED);
+ assertNotEquals(0, IFA_F_PERMANENT);
+ assertNotEquals(0, IFA_F_TENTATIVE);
}
+ @Test
public void testConstructors() throws SocketException {
LinkAddress address;
@@ -74,12 +82,14 @@
assertEquals(25, address.getPrefixLength());
assertEquals(0, address.getFlags());
assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
+ assertTrue(address.isIPv4());
address = new LinkAddress(V6_ADDRESS, 127);
assertEquals(V6_ADDRESS, address.getAddress());
assertEquals(127, address.getPrefixLength());
assertEquals(0, address.getFlags());
assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
+ assertTrue(address.isIPv6());
// Nonsensical flags/scopes or combinations thereof are acceptable.
address = new LinkAddress(V6 + "/64", IFA_F_DEPRECATED | IFA_F_PERMANENT, RT_SCOPE_LINK);
@@ -87,12 +97,14 @@
assertEquals(64, address.getPrefixLength());
assertEquals(IFA_F_DEPRECATED | IFA_F_PERMANENT, address.getFlags());
assertEquals(RT_SCOPE_LINK, address.getScope());
+ assertTrue(address.isIPv6());
address = new LinkAddress(V4 + "/23", 123, 456);
assertEquals(V4_ADDRESS, address.getAddress());
assertEquals(23, address.getPrefixLength());
assertEquals(123, address.getFlags());
assertEquals(456, address.getScope());
+ assertTrue(address.isIPv4());
// InterfaceAddress doesn't have a constructor. Fetch some from an interface.
List<InterfaceAddress> addrs = NetworkInterface.getByName("lo").getInterfaceAddresses();
@@ -174,6 +186,7 @@
} catch(IllegalArgumentException expected) {}
}
+ @Test
public void testAddressScopes() {
assertEquals(RT_SCOPE_HOST, new LinkAddress("::/128").getScope());
assertEquals(RT_SCOPE_HOST, new LinkAddress("0.0.0.0/32").getScope());
@@ -216,6 +229,7 @@
assertFalse(l2 + " unexpectedly equal to " + l1, l2.equals(l1));
}
+ @Test
public void testEqualsAndSameAddressAs() {
LinkAddress l1, l2, l3;
@@ -293,26 +307,17 @@
assertIsSameAddressAs(l1, l2);
}
+ @Test
public void testHashCode() {
- LinkAddress l;
+ LinkAddress l1, l2;
- l = new LinkAddress(V4_ADDRESS, 23);
- assertEquals(-982787, l.hashCode());
+ l1 = new LinkAddress(V4_ADDRESS, 23);
+ l2 = new LinkAddress(V4_ADDRESS, 23, 0, RT_SCOPE_HOST);
+ assertNotEquals(l1.hashCode(), l2.hashCode());
- l = new LinkAddress(V4_ADDRESS, 23, 0, RT_SCOPE_HOST);
- assertEquals(-971865, l.hashCode());
-
- l = new LinkAddress(V4_ADDRESS, 27);
- assertEquals(-982743, l.hashCode());
-
- l = new LinkAddress(V6_ADDRESS, 64);
- assertEquals(1076522926, l.hashCode());
-
- l = new LinkAddress(V6_ADDRESS, 128);
- assertEquals(1076523630, l.hashCode());
-
- l = new LinkAddress(V6_ADDRESS, 128, IFA_F_TENTATIVE, RT_SCOPE_UNIVERSE);
- assertEquals(1076524846, l.hashCode());
+ l1 = new LinkAddress(V6_ADDRESS, 128);
+ l2 = new LinkAddress(V6_ADDRESS, 128, IFA_F_TENTATIVE, RT_SCOPE_UNIVERSE);
+ assertNotEquals(l1.hashCode(), l2.hashCode());
}
private LinkAddress passThroughParcel(LinkAddress l) {
@@ -334,6 +339,7 @@
assertEquals(l, l2);
}
+ @Test
public void testParceling() {
LinkAddress l;
@@ -352,6 +358,7 @@
assertFalse(msg, l.isGlobalPreferred());
}
+ @Test
public void testIsGlobalPreferred() {
LinkAddress l;
diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
index 45525e6..d29a94b 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -25,6 +25,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
@@ -45,6 +46,7 @@
import android.net.NetworkStats;
import android.net.RouteInfo;
import android.net.util.SharedLog;
+import android.os.ConditionVariable;
import android.os.Handler;
import android.os.Looper;
import android.os.INetworkManagementService;
@@ -112,6 +114,12 @@
Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0);
}
+ private void waitForIdle() {
+ ConditionVariable cv = new ConditionVariable();
+ new Handler(Looper.getMainLooper()).post(() -> { cv.open(); });
+ cv.block();
+ }
+
private OffloadController makeOffloadController() throws Exception {
OffloadController offload = new OffloadController(new Handler(Looper.getMainLooper()),
mHardware, mContentResolver, mNMService, new SharedLog("test"));
@@ -421,4 +429,68 @@
entry = stats.getValues(ethernetPosition, entry);
assertNetworkStats(ethernetIface, ethernetStats, entry);
}
+
+ @Test
+ public void testSetInterfaceQuota() throws Exception {
+ setupFunctioningHardwareInterface();
+ enableOffload();
+
+ final OffloadController offload = makeOffloadController();
+ offload.start();
+
+ final String ethernetIface = "eth1";
+ final String mobileIface = "rmnet_data0";
+ final long ethernetLimit = 12345;
+ final long mobileLimit = 12345678;
+
+ final LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName(ethernetIface);
+ offload.setUpstreamLinkProperties(lp);
+
+ ITetheringStatsProvider provider = mTetherStatsProviderCaptor.getValue();
+ final InOrder inOrder = inOrder(mHardware);
+ when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(true);
+ when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true);
+
+ // Applying an interface quota to the current upstream immediately sends it to the hardware.
+ provider.setInterfaceQuota(ethernetIface, ethernetLimit);
+ waitForIdle();
+ inOrder.verify(mHardware).setDataLimit(ethernetIface, ethernetLimit);
+ inOrder.verifyNoMoreInteractions();
+
+ // Applying an interface quota to another upstream does not take any immediate action.
+ provider.setInterfaceQuota(mobileIface, mobileLimit);
+ waitForIdle();
+ inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong());
+
+ // Switching to that upstream causes the quota to be applied if the parameters were applied
+ // correctly.
+ lp.setInterfaceName(mobileIface);
+ offload.setUpstreamLinkProperties(lp);
+ waitForIdle();
+ inOrder.verify(mHardware).setDataLimit(mobileIface, mobileLimit);
+
+ // Setting a limit of ITetheringStatsProvider.QUOTA_UNLIMITED causes the limit to be set
+ // to Long.MAX_VALUE.
+ provider.setInterfaceQuota(mobileIface, ITetheringStatsProvider.QUOTA_UNLIMITED);
+ waitForIdle();
+ inOrder.verify(mHardware).setDataLimit(mobileIface, Long.MAX_VALUE);
+
+ // If setting upstream parameters fails, then the data limit is not set.
+ when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(false);
+ lp.setInterfaceName(ethernetIface);
+ offload.setUpstreamLinkProperties(lp);
+ provider.setInterfaceQuota(mobileIface, mobileLimit);
+ waitForIdle();
+ inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong());
+
+ // If setting the data limit fails while changing upstreams, offload is stopped.
+ when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(true);
+ when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(false);
+ lp.setInterfaceName(mobileIface);
+ offload.setUpstreamLinkProperties(lp);
+ provider.setInterfaceQuota(mobileIface, mobileLimit);
+ waitForIdle();
+ inOrder.verify(mHardware).stopOffloadControl();
+ }
}