Merge "Change HFP Client API to support multi device"
diff --git a/api/current.txt b/api/current.txt
index df8919c..6e52af6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -17017,6 +17017,15 @@
method public boolean isTransitionalDifferent();
}
+ public final class ListFormatter {
+ method public java.lang.String format(java.lang.Object...);
+ method public java.lang.String format(java.util.Collection<?>);
+ method public static android.icu.text.ListFormatter getInstance(android.icu.util.ULocale);
+ method public static android.icu.text.ListFormatter getInstance(java.util.Locale);
+ method public static android.icu.text.ListFormatter getInstance();
+ method public java.lang.String getPatternForNumItems(int);
+ }
+
public abstract class LocaleDisplayNames {
method public abstract android.icu.text.DisplayContext getContext(android.icu.text.DisplayContext.Type);
method public abstract android.icu.text.LocaleDisplayNames.DialectHandling getDialectHandling();
@@ -17026,6 +17035,8 @@
method public static android.icu.text.LocaleDisplayNames getInstance(android.icu.util.ULocale, android.icu.text.DisplayContext...);
method public static android.icu.text.LocaleDisplayNames getInstance(java.util.Locale, android.icu.text.DisplayContext...);
method public abstract android.icu.util.ULocale getLocale();
+ method public java.util.List<android.icu.text.LocaleDisplayNames.UiListItem> getUiList(java.util.Set<android.icu.util.ULocale>, boolean, java.util.Comparator<java.lang.Object>);
+ method public abstract java.util.List<android.icu.text.LocaleDisplayNames.UiListItem> getUiListCompareWholeItems(java.util.Set<android.icu.util.ULocale>, java.util.Comparator<android.icu.text.LocaleDisplayNames.UiListItem>);
method public abstract java.lang.String keyDisplayName(java.lang.String);
method public abstract java.lang.String keyValueDisplayName(java.lang.String, java.lang.String);
method public abstract java.lang.String languageDisplayName(java.lang.String);
@@ -17045,9 +17056,19 @@
enum_constant public static final android.icu.text.LocaleDisplayNames.DialectHandling STANDARD_NAMES;
}
+ public static class LocaleDisplayNames.UiListItem {
+ ctor public LocaleDisplayNames.UiListItem(android.icu.util.ULocale, android.icu.util.ULocale, java.lang.String, java.lang.String);
+ method public static java.util.Comparator<android.icu.text.LocaleDisplayNames.UiListItem> getComparator(java.util.Comparator<java.lang.Object>, boolean);
+ field public final android.icu.util.ULocale minimized;
+ field public final android.icu.util.ULocale modified;
+ field public final java.lang.String nameInDisplayLocale;
+ field public final java.lang.String nameInSelf;
+ }
+
public class MeasureFormat extends android.icu.text.UFormat {
method public final boolean equals(java.lang.Object);
method public java.lang.StringBuffer format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition);
+ method public java.lang.StringBuilder formatMeasurePerUnit(android.icu.util.Measure, android.icu.util.MeasureUnit, java.lang.StringBuilder, java.text.FieldPosition);
method public final java.lang.String formatMeasures(android.icu.util.Measure...);
method public java.lang.StringBuilder formatMeasures(java.lang.StringBuilder, java.text.FieldPosition, android.icu.util.Measure...);
method public static android.icu.text.MeasureFormat getCurrencyFormat(android.icu.util.ULocale);
@@ -17516,6 +17537,14 @@
method public void setUpperCaseFirst(boolean);
}
+ public final class ScientificNumberFormatter {
+ method public java.lang.String format(java.lang.Object);
+ method public static android.icu.text.ScientificNumberFormatter getMarkupInstance(android.icu.util.ULocale, java.lang.String, java.lang.String);
+ method public static android.icu.text.ScientificNumberFormatter getMarkupInstance(android.icu.text.DecimalFormat, java.lang.String, java.lang.String);
+ method public static android.icu.text.ScientificNumberFormatter getSuperscriptInstance(android.icu.util.ULocale);
+ method public static android.icu.text.ScientificNumberFormatter getSuperscriptInstance(android.icu.text.DecimalFormat);
+ }
+
public abstract class SearchIterator {
ctor protected SearchIterator(java.text.CharacterIterator, android.icu.text.BreakIterator);
method public final int first();
@@ -18291,6 +18320,34 @@
method public long getToDate();
}
+ public final class EthiopicCalendar extends android.icu.util.CECalendar {
+ ctor public EthiopicCalendar();
+ ctor public EthiopicCalendar(android.icu.util.TimeZone);
+ ctor public EthiopicCalendar(java.util.Locale);
+ ctor public EthiopicCalendar(android.icu.util.ULocale);
+ ctor public EthiopicCalendar(android.icu.util.TimeZone, java.util.Locale);
+ ctor public EthiopicCalendar(android.icu.util.TimeZone, android.icu.util.ULocale);
+ ctor public EthiopicCalendar(int, int, int);
+ ctor public EthiopicCalendar(java.util.Date);
+ ctor public EthiopicCalendar(int, int, int, int, int, int);
+ method protected deprecated int handleGetExtendedYear();
+ method public boolean isAmeteAlemEra();
+ method public void setAmeteAlemEra(boolean);
+ field public static final int GENBOT = 8; // 0x8
+ field public static final int HAMLE = 10; // 0xa
+ field public static final int HEDAR = 2; // 0x2
+ field public static final int MEGABIT = 6; // 0x6
+ field public static final int MESKEREM = 0; // 0x0
+ field public static final int MIAZIA = 7; // 0x7
+ field public static final int NEHASSE = 11; // 0xb
+ field public static final int PAGUMEN = 12; // 0xc
+ field public static final int SENE = 9; // 0x9
+ field public static final int TAHSAS = 3; // 0x3
+ field public static final int TEKEMT = 1; // 0x1
+ field public static final int TER = 4; // 0x4
+ field public static final int YEKATIT = 5; // 0x5
+ }
+
public abstract interface Freezable<T> implements java.lang.Cloneable {
method public abstract T cloneAsThawed();
method public abstract T freeze();
@@ -18819,6 +18876,35 @@
enum_constant public static final android.icu.util.ULocale.Category FORMAT;
}
+ public final class UniversalTimeScale {
+ method public static android.icu.math.BigDecimal bigDecimalFrom(double, int);
+ method public static android.icu.math.BigDecimal bigDecimalFrom(long, int);
+ method public static android.icu.math.BigDecimal bigDecimalFrom(android.icu.math.BigDecimal, int);
+ method public static long from(long, int);
+ method public static long getTimeScaleValue(int, int);
+ method public static android.icu.math.BigDecimal toBigDecimal(long, int);
+ method public static android.icu.math.BigDecimal toBigDecimal(android.icu.math.BigDecimal, int);
+ method public static long toLong(long, int);
+ field public static final int DB2_TIME = 8; // 0x8
+ field public static final int DOTNET_DATE_TIME = 4; // 0x4
+ field public static final int EPOCH_OFFSET_PLUS_1_VALUE = 6; // 0x6
+ field public static final int EPOCH_OFFSET_VALUE = 1; // 0x1
+ field public static final int EXCEL_TIME = 7; // 0x7
+ field public static final int FROM_MAX_VALUE = 3; // 0x3
+ field public static final int FROM_MIN_VALUE = 2; // 0x2
+ field public static final int ICU4C_TIME = 2; // 0x2
+ 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 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
+ field public static final int UNIX_MICROSECONDS_TIME = 9; // 0x9
+ field public static final int UNIX_TIME = 1; // 0x1
+ field public static final int WINDOWS_FILE_TIME = 3; // 0x3
+ }
+
public abstract interface ValueIterator {
method public abstract boolean next(android.icu.util.ValueIterator.Element);
method public abstract void reset();
@@ -36894,7 +36980,7 @@
field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
field public static final java.lang.String ACTION_CONFIGURE_PHONE_ACCOUNT = "android.telecom.action.CONFIGURE_PHONE_ACCOUNT";
field public static final java.lang.String ACTION_DEFAULT_DIALER_CHANGED = "android.telecom.action.DEFAULT_DIALER_CHANGED";
- field public static final java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL";
+ field public static final deprecated java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL";
field public static final java.lang.String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS";
field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
field public static final java.lang.String ACTION_SHOW_MISSED_CALLS_NOTIFICATION = "android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION";
diff --git a/api/system-current.txt b/api/system-current.txt
index 70651db..17ec7a1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -10253,6 +10253,7 @@
field public static final java.lang.String FEATURE_SIP = "android.software.sip";
field public static final java.lang.String FEATURE_SIP_VOIP = "android.software.sip.voip";
field public static final java.lang.String FEATURE_TELEPHONY = "android.hardware.telephony";
+ field public static final java.lang.String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock";
field public static final java.lang.String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
field public static final java.lang.String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
field public static final deprecated java.lang.String FEATURE_TELEVISION = "android.hardware.type.television";
@@ -18229,6 +18230,15 @@
method public boolean isTransitionalDifferent();
}
+ public final class ListFormatter {
+ method public java.lang.String format(java.lang.Object...);
+ method public java.lang.String format(java.util.Collection<?>);
+ method public static android.icu.text.ListFormatter getInstance(android.icu.util.ULocale);
+ method public static android.icu.text.ListFormatter getInstance(java.util.Locale);
+ method public static android.icu.text.ListFormatter getInstance();
+ method public java.lang.String getPatternForNumItems(int);
+ }
+
public abstract class LocaleDisplayNames {
method public abstract android.icu.text.DisplayContext getContext(android.icu.text.DisplayContext.Type);
method public abstract android.icu.text.LocaleDisplayNames.DialectHandling getDialectHandling();
@@ -18238,6 +18248,8 @@
method public static android.icu.text.LocaleDisplayNames getInstance(android.icu.util.ULocale, android.icu.text.DisplayContext...);
method public static android.icu.text.LocaleDisplayNames getInstance(java.util.Locale, android.icu.text.DisplayContext...);
method public abstract android.icu.util.ULocale getLocale();
+ method public java.util.List<android.icu.text.LocaleDisplayNames.UiListItem> getUiList(java.util.Set<android.icu.util.ULocale>, boolean, java.util.Comparator<java.lang.Object>);
+ method public abstract java.util.List<android.icu.text.LocaleDisplayNames.UiListItem> getUiListCompareWholeItems(java.util.Set<android.icu.util.ULocale>, java.util.Comparator<android.icu.text.LocaleDisplayNames.UiListItem>);
method public abstract java.lang.String keyDisplayName(java.lang.String);
method public abstract java.lang.String keyValueDisplayName(java.lang.String, java.lang.String);
method public abstract java.lang.String languageDisplayName(java.lang.String);
@@ -18257,9 +18269,19 @@
enum_constant public static final android.icu.text.LocaleDisplayNames.DialectHandling STANDARD_NAMES;
}
+ public static class LocaleDisplayNames.UiListItem {
+ ctor public LocaleDisplayNames.UiListItem(android.icu.util.ULocale, android.icu.util.ULocale, java.lang.String, java.lang.String);
+ method public static java.util.Comparator<android.icu.text.LocaleDisplayNames.UiListItem> getComparator(java.util.Comparator<java.lang.Object>, boolean);
+ field public final android.icu.util.ULocale minimized;
+ field public final android.icu.util.ULocale modified;
+ field public final java.lang.String nameInDisplayLocale;
+ field public final java.lang.String nameInSelf;
+ }
+
public class MeasureFormat extends android.icu.text.UFormat {
method public final boolean equals(java.lang.Object);
method public java.lang.StringBuffer format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition);
+ method public java.lang.StringBuilder formatMeasurePerUnit(android.icu.util.Measure, android.icu.util.MeasureUnit, java.lang.StringBuilder, java.text.FieldPosition);
method public final java.lang.String formatMeasures(android.icu.util.Measure...);
method public java.lang.StringBuilder formatMeasures(java.lang.StringBuilder, java.text.FieldPosition, android.icu.util.Measure...);
method public static android.icu.text.MeasureFormat getCurrencyFormat(android.icu.util.ULocale);
@@ -18728,6 +18750,14 @@
method public void setUpperCaseFirst(boolean);
}
+ public final class ScientificNumberFormatter {
+ method public java.lang.String format(java.lang.Object);
+ method public static android.icu.text.ScientificNumberFormatter getMarkupInstance(android.icu.util.ULocale, java.lang.String, java.lang.String);
+ method public static android.icu.text.ScientificNumberFormatter getMarkupInstance(android.icu.text.DecimalFormat, java.lang.String, java.lang.String);
+ method public static android.icu.text.ScientificNumberFormatter getSuperscriptInstance(android.icu.util.ULocale);
+ method public static android.icu.text.ScientificNumberFormatter getSuperscriptInstance(android.icu.text.DecimalFormat);
+ }
+
public abstract class SearchIterator {
ctor protected SearchIterator(java.text.CharacterIterator, android.icu.text.BreakIterator);
method public final int first();
@@ -19503,6 +19533,34 @@
method public long getToDate();
}
+ public final class EthiopicCalendar extends android.icu.util.CECalendar {
+ ctor public EthiopicCalendar();
+ ctor public EthiopicCalendar(android.icu.util.TimeZone);
+ ctor public EthiopicCalendar(java.util.Locale);
+ ctor public EthiopicCalendar(android.icu.util.ULocale);
+ ctor public EthiopicCalendar(android.icu.util.TimeZone, java.util.Locale);
+ ctor public EthiopicCalendar(android.icu.util.TimeZone, android.icu.util.ULocale);
+ ctor public EthiopicCalendar(int, int, int);
+ ctor public EthiopicCalendar(java.util.Date);
+ ctor public EthiopicCalendar(int, int, int, int, int, int);
+ method protected deprecated int handleGetExtendedYear();
+ method public boolean isAmeteAlemEra();
+ method public void setAmeteAlemEra(boolean);
+ field public static final int GENBOT = 8; // 0x8
+ field public static final int HAMLE = 10; // 0xa
+ field public static final int HEDAR = 2; // 0x2
+ field public static final int MEGABIT = 6; // 0x6
+ field public static final int MESKEREM = 0; // 0x0
+ field public static final int MIAZIA = 7; // 0x7
+ field public static final int NEHASSE = 11; // 0xb
+ field public static final int PAGUMEN = 12; // 0xc
+ field public static final int SENE = 9; // 0x9
+ field public static final int TAHSAS = 3; // 0x3
+ field public static final int TEKEMT = 1; // 0x1
+ field public static final int TER = 4; // 0x4
+ field public static final int YEKATIT = 5; // 0x5
+ }
+
public abstract interface Freezable<T> implements java.lang.Cloneable {
method public abstract T cloneAsThawed();
method public abstract T freeze();
@@ -20031,6 +20089,35 @@
enum_constant public static final android.icu.util.ULocale.Category FORMAT;
}
+ public final class UniversalTimeScale {
+ method public static android.icu.math.BigDecimal bigDecimalFrom(double, int);
+ method public static android.icu.math.BigDecimal bigDecimalFrom(long, int);
+ method public static android.icu.math.BigDecimal bigDecimalFrom(android.icu.math.BigDecimal, int);
+ method public static long from(long, int);
+ method public static long getTimeScaleValue(int, int);
+ method public static android.icu.math.BigDecimal toBigDecimal(long, int);
+ method public static android.icu.math.BigDecimal toBigDecimal(android.icu.math.BigDecimal, int);
+ method public static long toLong(long, int);
+ field public static final int DB2_TIME = 8; // 0x8
+ field public static final int DOTNET_DATE_TIME = 4; // 0x4
+ field public static final int EPOCH_OFFSET_PLUS_1_VALUE = 6; // 0x6
+ field public static final int EPOCH_OFFSET_VALUE = 1; // 0x1
+ field public static final int EXCEL_TIME = 7; // 0x7
+ field public static final int FROM_MAX_VALUE = 3; // 0x3
+ field public static final int FROM_MIN_VALUE = 2; // 0x2
+ field public static final int ICU4C_TIME = 2; // 0x2
+ 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 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
+ field public static final int UNIX_MICROSECONDS_TIME = 9; // 0x9
+ field public static final int UNIX_TIME = 1; // 0x1
+ field public static final int WINDOWS_FILE_TIME = 3; // 0x3
+ }
+
public abstract interface ValueIterator {
method public abstract boolean next(android.icu.util.ValueIterator.Element);
method public abstract void reset();
@@ -35487,6 +35574,7 @@
field public static final java.lang.String BOOT_COUNT = "boot_count";
field public static final java.lang.String CONTACT_METADATA_SYNC_ENABLED = "contact_metadata_sync_enabled";
field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String CURATE_SAVED_OPEN_NETWORKS = "curate_saved_open_networks";
field public static final java.lang.String DATA_ROAMING = "data_roaming";
field public static final java.lang.String DEBUG_APP = "debug_app";
field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
@@ -40054,7 +40142,7 @@
field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
field public static final java.lang.String ACTION_CONFIGURE_PHONE_ACCOUNT = "android.telecom.action.CONFIGURE_PHONE_ACCOUNT";
field public static final java.lang.String ACTION_DEFAULT_DIALER_CHANGED = "android.telecom.action.DEFAULT_DIALER_CHANGED";
- field public static final java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL";
+ field public static final deprecated java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL";
field public static final java.lang.String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED";
field public static final java.lang.String ACTION_PHONE_ACCOUNT_UNREGISTERED = "android.telecom.action.PHONE_ACCOUNT_UNREGISTERED";
field public static final java.lang.String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS";
@@ -40769,6 +40857,7 @@
method public void enableVideoCalling(boolean);
method public boolean endCall();
method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
+ method public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
method public int getCallState();
method public android.os.PersistableBundle getCarrierConfig();
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
@@ -40842,6 +40931,7 @@
method public void listen(android.telephony.PhoneStateListener, int);
method public boolean needsOtaServiceProvisioning();
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
+ method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method public void setDataEnabled(boolean);
method public void setDataEnabled(int, boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
diff --git a/api/test-current.txt b/api/test-current.txt
index e1a4a06..dc3ea99 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -17034,6 +17034,15 @@
method public boolean isTransitionalDifferent();
}
+ public final class ListFormatter {
+ method public java.lang.String format(java.lang.Object...);
+ method public java.lang.String format(java.util.Collection<?>);
+ method public static android.icu.text.ListFormatter getInstance(android.icu.util.ULocale);
+ method public static android.icu.text.ListFormatter getInstance(java.util.Locale);
+ method public static android.icu.text.ListFormatter getInstance();
+ method public java.lang.String getPatternForNumItems(int);
+ }
+
public abstract class LocaleDisplayNames {
method public abstract android.icu.text.DisplayContext getContext(android.icu.text.DisplayContext.Type);
method public abstract android.icu.text.LocaleDisplayNames.DialectHandling getDialectHandling();
@@ -17043,6 +17052,8 @@
method public static android.icu.text.LocaleDisplayNames getInstance(android.icu.util.ULocale, android.icu.text.DisplayContext...);
method public static android.icu.text.LocaleDisplayNames getInstance(java.util.Locale, android.icu.text.DisplayContext...);
method public abstract android.icu.util.ULocale getLocale();
+ method public java.util.List<android.icu.text.LocaleDisplayNames.UiListItem> getUiList(java.util.Set<android.icu.util.ULocale>, boolean, java.util.Comparator<java.lang.Object>);
+ method public abstract java.util.List<android.icu.text.LocaleDisplayNames.UiListItem> getUiListCompareWholeItems(java.util.Set<android.icu.util.ULocale>, java.util.Comparator<android.icu.text.LocaleDisplayNames.UiListItem>);
method public abstract java.lang.String keyDisplayName(java.lang.String);
method public abstract java.lang.String keyValueDisplayName(java.lang.String, java.lang.String);
method public abstract java.lang.String languageDisplayName(java.lang.String);
@@ -17062,9 +17073,19 @@
enum_constant public static final android.icu.text.LocaleDisplayNames.DialectHandling STANDARD_NAMES;
}
+ public static class LocaleDisplayNames.UiListItem {
+ ctor public LocaleDisplayNames.UiListItem(android.icu.util.ULocale, android.icu.util.ULocale, java.lang.String, java.lang.String);
+ method public static java.util.Comparator<android.icu.text.LocaleDisplayNames.UiListItem> getComparator(java.util.Comparator<java.lang.Object>, boolean);
+ field public final android.icu.util.ULocale minimized;
+ field public final android.icu.util.ULocale modified;
+ field public final java.lang.String nameInDisplayLocale;
+ field public final java.lang.String nameInSelf;
+ }
+
public class MeasureFormat extends android.icu.text.UFormat {
method public final boolean equals(java.lang.Object);
method public java.lang.StringBuffer format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition);
+ method public java.lang.StringBuilder formatMeasurePerUnit(android.icu.util.Measure, android.icu.util.MeasureUnit, java.lang.StringBuilder, java.text.FieldPosition);
method public final java.lang.String formatMeasures(android.icu.util.Measure...);
method public java.lang.StringBuilder formatMeasures(java.lang.StringBuilder, java.text.FieldPosition, android.icu.util.Measure...);
method public static android.icu.text.MeasureFormat getCurrencyFormat(android.icu.util.ULocale);
@@ -17533,6 +17554,14 @@
method public void setUpperCaseFirst(boolean);
}
+ public final class ScientificNumberFormatter {
+ method public java.lang.String format(java.lang.Object);
+ method public static android.icu.text.ScientificNumberFormatter getMarkupInstance(android.icu.util.ULocale, java.lang.String, java.lang.String);
+ method public static android.icu.text.ScientificNumberFormatter getMarkupInstance(android.icu.text.DecimalFormat, java.lang.String, java.lang.String);
+ method public static android.icu.text.ScientificNumberFormatter getSuperscriptInstance(android.icu.util.ULocale);
+ method public static android.icu.text.ScientificNumberFormatter getSuperscriptInstance(android.icu.text.DecimalFormat);
+ }
+
public abstract class SearchIterator {
ctor protected SearchIterator(java.text.CharacterIterator, android.icu.text.BreakIterator);
method public final int first();
@@ -18308,6 +18337,34 @@
method public long getToDate();
}
+ public final class EthiopicCalendar extends android.icu.util.CECalendar {
+ ctor public EthiopicCalendar();
+ ctor public EthiopicCalendar(android.icu.util.TimeZone);
+ ctor public EthiopicCalendar(java.util.Locale);
+ ctor public EthiopicCalendar(android.icu.util.ULocale);
+ ctor public EthiopicCalendar(android.icu.util.TimeZone, java.util.Locale);
+ ctor public EthiopicCalendar(android.icu.util.TimeZone, android.icu.util.ULocale);
+ ctor public EthiopicCalendar(int, int, int);
+ ctor public EthiopicCalendar(java.util.Date);
+ ctor public EthiopicCalendar(int, int, int, int, int, int);
+ method protected deprecated int handleGetExtendedYear();
+ method public boolean isAmeteAlemEra();
+ method public void setAmeteAlemEra(boolean);
+ field public static final int GENBOT = 8; // 0x8
+ field public static final int HAMLE = 10; // 0xa
+ field public static final int HEDAR = 2; // 0x2
+ field public static final int MEGABIT = 6; // 0x6
+ field public static final int MESKEREM = 0; // 0x0
+ field public static final int MIAZIA = 7; // 0x7
+ field public static final int NEHASSE = 11; // 0xb
+ field public static final int PAGUMEN = 12; // 0xc
+ field public static final int SENE = 9; // 0x9
+ field public static final int TAHSAS = 3; // 0x3
+ field public static final int TEKEMT = 1; // 0x1
+ field public static final int TER = 4; // 0x4
+ field public static final int YEKATIT = 5; // 0x5
+ }
+
public abstract interface Freezable<T> implements java.lang.Cloneable {
method public abstract T cloneAsThawed();
method public abstract T freeze();
@@ -18836,6 +18893,35 @@
enum_constant public static final android.icu.util.ULocale.Category FORMAT;
}
+ public final class UniversalTimeScale {
+ method public static android.icu.math.BigDecimal bigDecimalFrom(double, int);
+ method public static android.icu.math.BigDecimal bigDecimalFrom(long, int);
+ method public static android.icu.math.BigDecimal bigDecimalFrom(android.icu.math.BigDecimal, int);
+ method public static long from(long, int);
+ method public static long getTimeScaleValue(int, int);
+ method public static android.icu.math.BigDecimal toBigDecimal(long, int);
+ method public static android.icu.math.BigDecimal toBigDecimal(android.icu.math.BigDecimal, int);
+ method public static long toLong(long, int);
+ field public static final int DB2_TIME = 8; // 0x8
+ field public static final int DOTNET_DATE_TIME = 4; // 0x4
+ field public static final int EPOCH_OFFSET_PLUS_1_VALUE = 6; // 0x6
+ field public static final int EPOCH_OFFSET_VALUE = 1; // 0x1
+ field public static final int EXCEL_TIME = 7; // 0x7
+ field public static final int FROM_MAX_VALUE = 3; // 0x3
+ field public static final int FROM_MIN_VALUE = 2; // 0x2
+ field public static final int ICU4C_TIME = 2; // 0x2
+ 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 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
+ field public static final int UNIX_MICROSECONDS_TIME = 9; // 0x9
+ field public static final int UNIX_TIME = 1; // 0x1
+ field public static final int WINDOWS_FILE_TIME = 3; // 0x3
+ }
+
public abstract interface ValueIterator {
method public abstract boolean next(android.icu.util.ValueIterator.Element);
method public abstract void reset();
@@ -36976,7 +37062,7 @@
field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
field public static final java.lang.String ACTION_CONFIGURE_PHONE_ACCOUNT = "android.telecom.action.CONFIGURE_PHONE_ACCOUNT";
field public static final java.lang.String ACTION_DEFAULT_DIALER_CHANGED = "android.telecom.action.DEFAULT_DIALER_CHANGED";
- field public static final java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL";
+ field public static final deprecated java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL";
field public static final java.lang.String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS";
field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
field public static final java.lang.String ACTION_SHOW_MISSED_CALLS_NOTIFICATION = "android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION";
diff --git a/cmds/uiautomator/library/Android.mk b/cmds/uiautomator/library/Android.mk
index 9017be2..f932388 100644
--- a/cmds/uiautomator/library/Android.mk
+++ b/cmds/uiautomator/library/Android.mk
@@ -36,7 +36,7 @@
# Generate the stub source files
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(uiautomator.core_src_files)
-LOCAL_JAVA_LIBRARIES := $(uiautomator.core_java_libraries)
+LOCAL_JAVA_LIBRARIES := $(uiautomator.core_java_libraries) legacy-android-test
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/core-src \
$(LOCAL_PATH)/testrunner-src
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 11e19f3..57ebe52 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1810,6 +1810,20 @@
public static final String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device supports telephony carrier restriction mechanism.
+ *
+ * <p>Devices declaring this feature must have an implementation of the
+ * {@link android.telephony.TelephonyManager#getAllowedCarriers} and
+ * {@link android.telephony.TelephonyManager#setAllowedCarriers}.
+ * @hide
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_TELEPHONY_CARRIERLOCK =
+ "android.hardware.telephony.carrierlock";
+
+ /**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports connecting to USB devices
* as the USB host.
diff --git a/core/java/android/net/INetworkScoreCache.aidl b/core/java/android/net/INetworkScoreCache.aidl
index 35601ce..1da7d67 100644
--- a/core/java/android/net/INetworkScoreCache.aidl
+++ b/core/java/android/net/INetworkScoreCache.aidl
@@ -34,7 +34,7 @@
* the current scores for each network for debugging purposes.
* @hide
*/
-interface INetworkScoreCache
+oneway interface INetworkScoreCache
{
void updateScores(in List<ScoredNetwork> networks);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 35fa210..b1dcb81 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7673,6 +7673,16 @@
"network_recommendations_enabled";
/**
+ * Value to specify if the Wi-Fi Framework should defer to
+ * {@link com.android.server.NetworkScoreService} for evaluating saved open networks.
+ *
+ * Type: int (0 for false, 1 for true)
+ * @hide
+ */
+ @SystemApi
+ public static final String CURATE_SAVED_OPEN_NETWORKS = "curate_saved_open_networks";
+
+ /**
* The number of milliseconds the {@link com.android.server.NetworkScoreService}
* will give a recommendation request to complete before returning a default response.
*
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index 28d9e5c..e2080b0 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -37,5 +37,7 @@
<activity android:name="com.android.carrierdefaultapp.CaptivePortalLaunchActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:excludeFromRecents="true"/>
+ <service android:name="com.android.carrierdefaultapp.ProvisionObserver"
+ android:permission="android.permission.BIND_JOB_SERVICE"/>
</application>
</manifest>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java
index bc0fa02..3fd89d9 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java
@@ -28,6 +28,10 @@
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive intent: " + intent.getAction());
+ if (ProvisionObserver.isDeferredForProvision(context, intent)) {
+ Log.d(TAG, "skip carrier actions during provisioning");
+ return;
+ }
List<Integer> actionList = CustomConfigLoader.loadCarrierActionList(context, intent);
for (int actionIdx : actionList) {
Log.d(TAG, "apply carrier action idx: " + actionIdx);
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/ProvisionObserver.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/ProvisionObserver.java
new file mode 100644
index 0000000..3e34f0a
--- /dev/null
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/ProvisionObserver.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.carrierdefaultapp;
+
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.internal.telephony.TelephonyIntents;
+
+/**
+ * Service to run {@link android.app.job.JobScheduler} job.
+ * Service to monitor when there is a change to conent URI
+ * {@link android.provider.Settings.Global#DEVICE_PROVISIONED DEVICE_PROVISIONED}
+ */
+public class ProvisionObserver extends JobService {
+
+ private static final String TAG = ProvisionObserver.class.getSimpleName();
+ public static final int PROVISION_OBSERVER_REEVALUATION_JOB_ID = 1;
+ // minimum & maximum update delay TBD
+ private static final int CONTENT_UPDATE_DELAY_MS = 100;
+ private static final int CONTENT_MAX_DELAY_MS = 200;
+
+ @Override
+ public boolean onStartJob(JobParameters jobParameters) {
+ switch (jobParameters.getJobId()) {
+ case PROVISION_OBSERVER_REEVALUATION_JOB_ID:
+ if (isProvisioned(this)) {
+ Log.d(TAG, "device provisioned, force network re-evaluation");
+ final ConnectivityManager connMgr = ConnectivityManager.from(this);
+ Network[] info = connMgr.getAllNetworks();
+ for (Network nw : info) {
+ final NetworkCapabilities nc = connMgr.getNetworkCapabilities(nw);
+ if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+ && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
+ // force connectivity re-evaluation to assume skipped carrier actions.
+ // one of the following calls will match the last evaluation.
+ connMgr.reportNetworkConnectivity(nw, true);
+ connMgr.reportNetworkConnectivity(nw, false);
+ break;
+ }
+ }
+ }
+ default:
+ break;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onStopJob(JobParameters jobParameters) {
+ return false;
+ }
+
+ // Returns true if the device is not provisioned yet (in setup wizard), false otherwise
+ private static boolean isProvisioned(Context context) {
+ return Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 0) == 1;
+ }
+
+ /**
+ * Static utility function to schedule a job to execute upon the change of content URI
+ * {@link android.provider.Settings.Global#DEVICE_PROVISIONED DEVICE_PROVISIONED}.
+ * @param context The context used to retrieve the {@link ComponentName} and system services
+ * @return true carrier actions are deferred due to phone provisioning process, false otherwise
+ */
+ public static boolean isDeferredForProvision(Context context, Intent intent) {
+ if (isProvisioned(context)) {
+ return false;
+ }
+ int jobId;
+ switch(intent.getAction()) {
+ case TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED:
+ jobId = PROVISION_OBSERVER_REEVALUATION_JOB_ID;
+ break;
+ default:
+ return false;
+ }
+ final JobScheduler jobScheduler = (JobScheduler) context.getSystemService(
+ Context.JOB_SCHEDULER_SERVICE);
+ final JobInfo job = new JobInfo.Builder(jobId,
+ new ComponentName(context, ProvisionObserver.class))
+ .addTriggerContentUri(new JobInfo.TriggerContentUri(
+ Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), 0))
+ .setTriggerContentUpdateDelay(CONTENT_UPDATE_DELAY_MS)
+ .setTriggerContentMaxDelay(CONTENT_MAX_DELAY_MS)
+ .build();
+ jobScheduler.schedule(job);
+ return true;
+ }
+}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index b3627ad..8c38ed6 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3130,10 +3130,7 @@
Settings.Global.TETHER_SUPPORTED, defaultVal) != 0)
&& !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
return tetherEnabledInSettings && mUserManager.isAdminUser() &&
- ((mTethering.getTetherableUsbRegexs().length != 0 ||
- mTethering.getTetherableWifiRegexs().length != 0 ||
- mTethering.getTetherableBluetoothRegexs().length != 0) &&
- mTethering.getUpstreamIfaceTypes().length != 0);
+ mTethering.hasTetherableConfiguration();
}
@Override
@@ -5504,6 +5501,18 @@
}
}
+ // Turn Always-on VPN off
+ if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mKeyStore.delete(Credentials.LOCKDOWN_VPN);
+ mLockdownEnabled = false;
+ setLockdownTracker(null);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
// Turn VPN off
VpnConfig vpnConfig = getVpnConfig(userId);
if (vpnConfig != null) {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index bd88ddb..b0e4509 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -76,6 +76,7 @@
import com.android.server.connectivity.tethering.IControlsTethering;
import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
import com.android.server.connectivity.tethering.IPv6TetheringInterfaceServices;
+import com.android.server.connectivity.tethering.TetheringConfiguration;
import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
import com.android.server.net.BaseNetworkObserver;
@@ -113,23 +114,11 @@
private static final SparseArray<String> sMagicDecoderRing =
MessageUtils.findMessageNames(messageClasses);
- // TODO - remove both of these - should be part of interface inspection/selection stuff
- private String[] mTetherableUsbRegexs;
- private String[] mTetherableWifiRegexs;
- private String[] mTetherableBluetoothRegexs;
- private Collection<Integer> mUpstreamIfaceTypes;
+ private volatile TetheringConfiguration mConfig;
// used to synchronize public access to members
private final Object mPublicSync;
- private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
- private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
- private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);
-
- // if we have to connect to mobile, what APN type should we use? Calculated by examining the
- // upstream type list and the DUN_REQUIRED secure-setting
- private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
-
private final INetworkManagementService mNMService;
private final INetworkStatsService mStatsService;
private final INetworkPolicyManager mPolicyManager;
@@ -155,24 +144,6 @@
private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(Resources
.getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable));
- // USB is 192.168.42.1 and 255.255.255.0
- // Wifi is 192.168.43.1 and 255.255.255.0
- // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
- // with 255.255.255.0
- // P2P is 192.168.49.1 and 255.255.255.0
-
- private String[] mDhcpRange;
- private static final String[] DHCP_DEFAULT_RANGE = {
- "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
- "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
- "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
- "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254",
- };
-
- private String[] mDefaultDnsServers;
- private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
- private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
-
private final StateMachine mTetherMasterSM;
private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
private String mCurrentUpstreamIface;
@@ -221,19 +192,8 @@
filter.addDataScheme("file");
mContext.registerReceiver(mStateReceiver, filter, null, mTetherMasterSM.getHandler());
- mDhcpRange = context.getResources().getStringArray(
- com.android.internal.R.array.config_tether_dhcp_range);
- if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
- mDhcpRange = DHCP_DEFAULT_RANGE;
- }
-
// load device config info
updateConfiguration();
-
- // TODO - remove and rely on real notifications of the current iface
- mDefaultDnsServers = new String[2];
- mDefaultDnsServers[0] = DNS_DEFAULT_SERVER1;
- mDefaultDnsServers[1] = DNS_DEFAULT_SERVER2;
}
// We can't do this once in the Tethering() constructor and cache the value, because the
@@ -242,30 +202,8 @@
return (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
}
- void updateConfiguration() {
- String[] tetherableUsbRegexs = mContext.getResources().getStringArray(
- com.android.internal.R.array.config_tether_usb_regexs);
- String[] tetherableWifiRegexs = mContext.getResources().getStringArray(
- com.android.internal.R.array.config_tether_wifi_regexs);
- String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray(
- com.android.internal.R.array.config_tether_bluetooth_regexs);
-
- int ifaceTypes[] = mContext.getResources().getIntArray(
- com.android.internal.R.array.config_tether_upstream_types);
- Collection<Integer> upstreamIfaceTypes = new ArrayList<>();
- for (int i : ifaceTypes) {
- upstreamIfaceTypes.add(new Integer(i));
- }
-
- synchronized (mPublicSync) {
- mTetherableUsbRegexs = tetherableUsbRegexs;
- mTetherableWifiRegexs = tetherableWifiRegexs;
- mTetherableBluetoothRegexs = tetherableBluetoothRegexs;
- mUpstreamIfaceTypes = upstreamIfaceTypes;
- }
-
- // check if the upstream type list needs to be modified due to secure-settings
- checkDunRequired();
+ private void updateConfiguration() {
+ mConfig = new TetheringConfiguration(mContext);
}
@Override
@@ -305,39 +243,14 @@
interfaceStatusChanged(iface, up);
}
- private boolean isUsb(String iface) {
- synchronized (mPublicSync) {
- for (String regex : mTetherableUsbRegexs) {
- if (iface.matches(regex)) return true;
- }
- return false;
- }
- }
-
- private boolean isWifi(String iface) {
- synchronized (mPublicSync) {
- for (String regex : mTetherableWifiRegexs) {
- if (iface.matches(regex)) return true;
- }
- return false;
- }
- }
-
- private boolean isBluetooth(String iface) {
- synchronized (mPublicSync) {
- for (String regex : mTetherableBluetoothRegexs) {
- if (iface.matches(regex)) return true;
- }
- return false;
- }
- }
-
private int ifaceNameToType(String iface) {
- if (isWifi(iface)) {
+ final TetheringConfiguration cfg = mConfig;
+
+ if (cfg.isWifi(iface)) {
return ConnectivityManager.TETHERING_WIFI;
- } else if (isUsb(iface)) {
+ } else if (cfg.isUsb(iface)) {
return ConnectivityManager.TETHERING_USB;
- } else if (isBluetooth(iface)) {
+ } else if (cfg.isBluetooth(iface)) {
return ConnectivityManager.TETHERING_BLUETOOTH;
}
return ConnectivityManager.TETHERING_INVALID;
@@ -667,6 +580,8 @@
boolean usbTethered = false;
boolean bluetoothTethered = false;
+ final TetheringConfiguration cfg = mConfig;
+
synchronized (mPublicSync) {
for (int i = 0; i < mTetherStates.size(); i++) {
TetherState tetherState = mTetherStates.valueAt(i);
@@ -676,11 +591,11 @@
} else if (tetherState.mLastState == IControlsTethering.STATE_AVAILABLE) {
availableList.add(iface);
} else if (tetherState.mLastState == IControlsTethering.STATE_TETHERED) {
- if (isUsb(iface)) {
+ if (cfg.isUsb(iface)) {
usbTethered = true;
- } else if (isWifi(iface)) {
+ } else if (cfg.isWifi(iface)) {
wifiTethered = true;
- } else if (isBluetooth(iface)) {
+ } else if (cfg.isBluetooth(iface)) {
bluetoothTethered = true;
}
activeList.add(iface);
@@ -895,17 +810,33 @@
}
}
- // TODO - return copies so people can't tamper
+ public TetheringConfiguration getTetheringConfiguration() {
+ return mConfig;
+ }
+
+ public boolean hasTetherableConfiguration() {
+ final TetheringConfiguration cfg = mConfig;
+ final boolean hasDownstreamConfiguration =
+ (cfg.tetherableUsbRegexs.length != 0) ||
+ (cfg.tetherableWifiRegexs.length != 0) ||
+ (cfg.tetherableBluetoothRegexs.length != 0);
+ final boolean hasUpstreamConfiguration = !cfg.preferredUpstreamIfaceTypes.isEmpty();
+
+ return hasDownstreamConfiguration && hasUpstreamConfiguration;
+ }
+
+ // TODO - update callers to use getTetheringConfiguration(),
+ // which has only final members.
public String[] getTetherableUsbRegexs() {
- return mTetherableUsbRegexs;
+ return copy(mConfig.tetherableUsbRegexs);
}
public String[] getTetherableWifiRegexs() {
- return mTetherableWifiRegexs;
+ return copy(mConfig.tetherableWifiRegexs);
}
public String[] getTetherableBluetoothRegexs() {
- return mTetherableBluetoothRegexs;
+ return copy(mConfig.tetherableBluetoothRegexs);
}
public int setUsbTethering(boolean enable) {
@@ -941,61 +872,6 @@
return ConnectivityManager.TETHER_ERROR_NO_ERROR;
}
- public int[] getUpstreamIfaceTypes() {
- int values[];
- synchronized (mPublicSync) {
- updateConfiguration(); // TODO - remove?
- values = new int[mUpstreamIfaceTypes.size()];
- Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
- for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
- values[i] = iterator.next();
- }
- }
- return values;
- }
-
- private void checkDunRequired() {
- int secureSetting = 2;
- TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- if (tm != null) {
- secureSetting = tm.getTetherApnRequired();
- }
- synchronized (mPublicSync) {
- // 2 = not set, 0 = DUN not required, 1 = DUN required
- if (secureSetting != 2) {
- int requiredApn = (secureSetting == 1 ?
- ConnectivityManager.TYPE_MOBILE_DUN :
- ConnectivityManager.TYPE_MOBILE_HIPRI);
- if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
- while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
- mUpstreamIfaceTypes.remove(MOBILE_TYPE);
- }
- while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
- mUpstreamIfaceTypes.remove(HIPRI_TYPE);
- }
- if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
- mUpstreamIfaceTypes.add(DUN_TYPE);
- }
- } else {
- while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
- mUpstreamIfaceTypes.remove(DUN_TYPE);
- }
- if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
- mUpstreamIfaceTypes.add(MOBILE_TYPE);
- }
- if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
- mUpstreamIfaceTypes.add(HIPRI_TYPE);
- }
- }
- }
- if (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
- mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN;
- } else {
- mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI;
- }
- }
- }
-
// TODO review API - maybe return ArrayList<String> here and below?
public String[] getTetheredIfaces() {
ArrayList<String> list = new ArrayList<String>();
@@ -1024,7 +900,7 @@
}
public String[] getTetheredDhcpRanges() {
- return mDhcpRange;
+ return mConfig.dhcpRanges;
}
public String[] getErroredIfaces() {
@@ -1099,8 +975,6 @@
private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
private final IPv6TetheringCoordinator mIPv6TetheringCoordinator;
- private int mPreviousMobileType = ConnectivityManager.TYPE_NONE;
-
private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
TetherMasterSM(String name, Looper looper) {
@@ -1134,46 +1008,18 @@
return false;
}
- protected boolean requestUpstreamMobileConnection(int apnType) {
- if (apnType == ConnectivityManager.TYPE_NONE) { return false; }
-
- if (apnType != mPreviousMobileType) {
- // Unregister any previous mobile upstream callback because
- // this request, if any, will be different.
- unrequestUpstreamMobileConnection();
- }
-
- if (mUpstreamNetworkMonitor.mobileNetworkRequested()) {
- // Looks like we already filed a request for this apnType.
- return true;
- }
-
- switch (apnType) {
- case ConnectivityManager.TYPE_MOBILE_DUN:
- case ConnectivityManager.TYPE_MOBILE:
- case ConnectivityManager.TYPE_MOBILE_HIPRI:
- mPreviousMobileType = apnType;
- break;
- default:
- return false;
- }
-
- // TODO: Replace this with a call to pass the current tethering
- // configuration to mUpstreamNetworkMonitor and let it handle
- // choosing APN type accordingly.
- mUpstreamNetworkMonitor.updateMobileRequiresDun(
- apnType == ConnectivityManager.TYPE_MOBILE_DUN);
-
+ protected boolean requestUpstreamMobileConnection() {
+ mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired);
mUpstreamNetworkMonitor.registerMobileNetworkRequest();
return true;
}
protected void unrequestUpstreamMobileConnection() {
mUpstreamNetworkMonitor.releaseMobileNetworkRequest();
- mPreviousMobileType = ConnectivityManager.TYPE_NONE;
}
protected boolean turnOnMasterTetherSettings() {
+ final TetheringConfiguration cfg = mConfig;
try {
mNMService.setIpForwardingEnabled(true);
} catch (Exception e) {
@@ -1181,11 +1027,11 @@
return false;
}
try {
- mNMService.startTethering(mDhcpRange);
+ mNMService.startTethering(cfg.dhcpRanges);
} catch (Exception e) {
try {
mNMService.stopTethering();
- mNMService.startTethering(mDhcpRange);
+ mNMService.startTethering(cfg.dhcpRanges);
} catch (Exception ee) {
transitionTo(mStartTetheringErrorState);
return false;
@@ -1218,29 +1064,31 @@
updateConfiguration(); // TODO - remove?
- synchronized (mPublicSync) {
- if (VDBG) {
- Log.d(TAG, "chooseUpstreamType has upstream iface types:");
- for (Integer netType : mUpstreamIfaceTypes) {
- Log.d(TAG, " " + netType);
- }
- }
-
- for (Integer netType : mUpstreamIfaceTypes) {
- NetworkInfo info = cm.getNetworkInfo(netType.intValue());
- // TODO: if the network is suspended we should consider
- // that to be the same as connected here.
- if ((info != null) && info.isConnected()) {
- upType = netType.intValue();
- break;
- }
+ final TetheringConfiguration cfg = mConfig;
+ if (VDBG) {
+ Log.d(TAG, "chooseUpstreamType has upstream iface types:");
+ for (Integer netType : cfg.preferredUpstreamIfaceTypes) {
+ Log.d(TAG, " " + netType);
}
}
+ for (Integer netType : cfg.preferredUpstreamIfaceTypes) {
+ NetworkInfo info = cm.getNetworkInfo(netType.intValue());
+ // TODO: if the network is suspended we should consider
+ // that to be the same as connected here.
+ if ((info != null) && info.isConnected()) {
+ upType = netType.intValue();
+ break;
+ }
+ }
+
+ final int preferredUpstreamMobileApn = cfg.isDunRequired
+ ? ConnectivityManager.TYPE_MOBILE_DUN
+ : ConnectivityManager.TYPE_MOBILE_HIPRI;
if (DBG) {
Log.d(TAG, "chooseUpstreamType(" + tryCell + "),"
+ " preferredApn="
- + ConnectivityManager.getNetworkTypeName(mPreferredUpstreamMobileApn)
+ + ConnectivityManager.getNetworkTypeName(preferredUpstreamMobileApn)
+ ", got type="
+ ConnectivityManager.getNetworkTypeName(upType));
}
@@ -1249,11 +1097,10 @@
case ConnectivityManager.TYPE_MOBILE_DUN:
case ConnectivityManager.TYPE_MOBILE_HIPRI:
// If we're on DUN, put our own grab on it.
- requestUpstreamMobileConnection(upType);
+ requestUpstreamMobileConnection();
break;
case ConnectivityManager.TYPE_NONE:
- if (tryCell &&
- requestUpstreamMobileConnection(mPreferredUpstreamMobileApn)) {
+ if (tryCell && requestUpstreamMobileConnection()) {
// We think mobile should be coming up; don't set a retry.
} else {
sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
@@ -1311,7 +1158,8 @@
}
protected void setDnsForwarders(final Network network, final LinkProperties lp) {
- String[] dnsServers = mDefaultDnsServers;
+ // TODO: Set v4 and/or v6 DNS per available connectivity.
+ String[] dnsServers = mConfig.defaultIPv4DNS;
final Collection<InetAddress> dnses = lp.getDnsServers();
// TODO: Properly support the absence of DNS servers.
if (dnses != null && !dnses.isEmpty()) {
@@ -1720,9 +1568,10 @@
pw.println("Tethering:");
pw.increaseIndent();
- pw.print("mUpstreamIfaceTypes:");
+ final TetheringConfiguration cfg = mConfig;
+ pw.print("preferredUpstreamIfaceTypes:");
synchronized (mPublicSync) {
- for (Integer netType : mUpstreamIfaceTypes) {
+ for (Integer netType : cfg.preferredUpstreamIfaceTypes) {
pw.print(" " + ConnectivityManager.getNetworkTypeName(netType));
}
pw.println();
@@ -1802,4 +1651,8 @@
mTetherStates.put(iface, tetherState);
tetherState.mStateMachine.start();
}
+
+ private static String[] copy(String[] strarray) {
+ return Arrays.copyOf(strarray, strarray.length);
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
new file mode 100644
index 0000000..14d06cc
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.tethering;
+
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
+import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+
+/**
+ * A utility class to encapsulate the various tethering configuration elements.
+ *
+ * This configuration data includes elements describing upstream properties
+ * (preferred and required types of upstream connectivity as well as default
+ * DNS servers to use if none are available) and downstream properties (such
+ * as regular expressions use to match suitable downstream interfaces and the
+ * DHCPv4 ranges to use).
+ *
+ * @hide
+ */
+public class TetheringConfiguration {
+ private static final String TAG = TetheringConfiguration.class.getSimpleName();
+
+ private static final int DUN_NOT_REQUIRED = 0;
+ private static final int DUN_REQUIRED = 1;
+ private static final int DUN_UNSPECIFIED = 2;
+
+ // USB is 192.168.42.1 and 255.255.255.0
+ // Wifi is 192.168.43.1 and 255.255.255.0
+ // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
+ // with 255.255.255.0
+ // P2P is 192.168.49.1 and 255.255.255.0
+ private static final String[] DHCP_DEFAULT_RANGE = {
+ "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
+ "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
+ "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
+ "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254",
+ };
+
+ private final String[] DEFAULT_IPV4_DNS = {"8.8.4.4", "8.8.8.8"};
+
+ public final String[] tetherableUsbRegexs;
+ public final String[] tetherableWifiRegexs;
+ public final String[] tetherableBluetoothRegexs;
+ public final boolean isDunRequired;
+ public final Collection<Integer> preferredUpstreamIfaceTypes;
+ public final String[] dhcpRanges;
+ public final String[] defaultIPv4DNS;
+
+ public TetheringConfiguration(Context ctx) {
+ tetherableUsbRegexs = ctx.getResources().getStringArray(
+ com.android.internal.R.array.config_tether_usb_regexs);
+ tetherableWifiRegexs = ctx.getResources().getStringArray(
+ com.android.internal.R.array.config_tether_wifi_regexs);
+ tetherableBluetoothRegexs = ctx.getResources().getStringArray(
+ com.android.internal.R.array.config_tether_bluetooth_regexs);
+
+ isDunRequired = checkDunRequired(ctx);
+ preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(ctx, isDunRequired);
+
+ dhcpRanges = getDhcpRanges(ctx);
+ defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
+ }
+
+ public boolean isUsb(String iface) {
+ return matchesDownstreamRegexs(iface, tetherableUsbRegexs);
+ }
+
+ public boolean isWifi(String iface) {
+ return matchesDownstreamRegexs(iface, tetherableWifiRegexs);
+ }
+
+ public boolean isBluetooth(String iface) {
+ return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs);
+ }
+
+ private static boolean checkDunRequired(Context ctx) {
+ final TelephonyManager tm = ctx.getSystemService(TelephonyManager.class);
+ final int secureSetting =
+ (tm != null) ? tm.getTetherApnRequired() : DUN_UNSPECIFIED;
+ return (secureSetting == DUN_REQUIRED);
+ }
+
+ private static Collection<Integer> getUpstreamIfaceTypes(Context ctx, boolean requiresDun) {
+ final int ifaceTypes[] = ctx.getResources().getIntArray(
+ com.android.internal.R.array.config_tether_upstream_types);
+ final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);
+ for (int i : ifaceTypes) {
+ switch (i) {
+ case TYPE_MOBILE:
+ case TYPE_MOBILE_HIPRI:
+ if (requiresDun) continue;
+ break;
+ case TYPE_MOBILE_DUN:
+ if (!requiresDun) continue;
+ break;
+ }
+ upstreamIfaceTypes.add(i);
+ }
+
+ // Fix up upstream interface types for DUN or mobile. NOTE: independent
+ // of the value of |requiresDun|, cell data of one form or another is
+ // *always* an upstream, regardless of the upstream interface types
+ // specified by configuration resources.
+ if (requiresDun) {
+ if (!upstreamIfaceTypes.contains(TYPE_MOBILE_DUN)) {
+ upstreamIfaceTypes.add(TYPE_MOBILE_DUN);
+ }
+ } else {
+ if (!upstreamIfaceTypes.contains(TYPE_MOBILE)) {
+ upstreamIfaceTypes.add(TYPE_MOBILE);
+ }
+ if (!upstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI)) {
+ upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI);
+ }
+ }
+
+ return upstreamIfaceTypes;
+ }
+
+ private static boolean matchesDownstreamRegexs(String iface, String[] regexs) {
+ for (String regex : regexs) {
+ if (iface.matches(regex)) return true;
+ }
+ return false;
+ }
+
+ private static String[] getDhcpRanges(Context ctx) {
+ final String[] fromResource = ctx.getResources().getStringArray(
+ com.android.internal.R.array.config_tether_dhcp_range);
+ if ((fromResource.length > 0) && (fromResource.length % 2 == 0)) {
+ return fromResource;
+ }
+ return copy(DHCP_DEFAULT_RANGE);
+ }
+
+ private static String[] copy(String[] strarray) {
+ return Arrays.copyOf(strarray, strarray.length);
+ }
+}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 61c2eac..58600bb 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -285,6 +285,7 @@
int activeColorMode) {
List<Integer> pendingColorModes = new ArrayList<>();
+ if (colorModes == null) return false;
// Build an updated list of all existing color modes.
boolean colorModesAdded = false;
for (int colorMode: colorModes) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 00e8f9f..ba7b6a1 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -58,12 +58,15 @@
* Input: get*Extra field {@link #EXTRA_PHONE_ACCOUNT_HANDLE} contains the component name of the
* {@link android.telecom.ConnectionService} that Telecom should bind to. Telecom will then
* ask the connection service for more information about the call prior to showing any UI.
+ *
+ * @deprecated Use {@link #addNewIncomingCall} instead.
*/
public static final String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL";
/**
* Similar to {@link #ACTION_INCOMING_CALL}, but is used only by Telephony to add a new
* sim-initiated MO call for carrier testing.
+ * @deprecated Use {@link #addNewUnknownCall} instead.
* @hide
*/
public static final String ACTION_NEW_UNKNOWN_CALL = "android.telecom.action.NEW_UNKNOWN_CALL";
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 5a15009..307dc1a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5682,10 +5682,17 @@
* Set the allowed carrier list for slotId
* Require system privileges. In the future we may add this to carrier APIs.
*
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE}
+ *
+ * <p>This method works only on devices with {@link
+ * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled.
+ *
* @return The number of carriers set successfully. Should be length of
* carrierList on success; -1 on error.
* @hide
*/
+ @SystemApi
public int setAllowedCarriers(int slotId, List<CarrierIdentifier> carriers) {
try {
ITelephony service = getITelephony();
@@ -5694,6 +5701,8 @@
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e);
+ } catch (NullPointerException e) {
+ Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e);
}
return -1;
}
@@ -5702,10 +5711,17 @@
* Get the allowed carrier list for slotId.
* Require system privileges. In the future we may add this to carrier APIs.
*
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
+ *
+ * <p>This method returns valid data on devices with {@link
+ * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled.
+ *
* @return List of {@link android.telephony.CarrierIdentifier}; empty list
* means all carriers are allowed.
* @hide
*/
+ @SystemApi
public List<CarrierIdentifier> getAllowedCarriers(int slotId) {
try {
ITelephony service = getITelephony();
@@ -5714,6 +5730,8 @@
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getAllowedCarriers", e);
+ } catch (NullPointerException e) {
+ Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e);
}
return new ArrayList<CarrierIdentifier>(0);
}
diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
index b4d4871..1e67769 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.reset;
import android.content.Context;
@@ -69,12 +70,13 @@
@Test
public void testDoesNothingBeforeStarted() {
- UpstreamNetworkMonitor unm = new UpstreamNetworkMonitor(null, null, EVENT_UNM_UPDATE);
- assertFalse(unm.mobileNetworkRequested());
- // Given a null Context, and therefore a null ConnectivityManager,
- // these would cause an exception, if they actually attempted anything.
- unm.updateMobileRequiresDun(true);
- unm.updateMobileRequiresDun(false);
+ assertTrue(mCM.hasNoCallbacks());
+ assertFalse(mUNM.mobileNetworkRequested());
+
+ mUNM.updateMobileRequiresDun(true);
+ assertTrue(mCM.hasNoCallbacks());
+ mUNM.updateMobileRequiresDun(false);
+ assertTrue(mCM.hasNoCallbacks());
}
@Test
@@ -85,7 +87,7 @@
assertEquals(1, mCM.trackingDefault.size());
mUNM.stop();
- assertTrue(mCM.isEmpty());
+ assertTrue(mCM.hasNoCallbacks());
}
@Test
@@ -97,11 +99,11 @@
assertTrue(mCM.isListeningForDun());
mUNM.stop();
- assertTrue(mCM.isEmpty());
+ assertTrue(mCM.hasNoCallbacks());
}
@Test
- public void testCanRequestMobileNetwork() throws Exception {
+ public void testRequestsMobileNetwork() throws Exception {
assertFalse(mUNM.mobileNetworkRequested());
assertEquals(0, mCM.requested.size());
@@ -115,19 +117,16 @@
mUNM.registerMobileNetworkRequest();
assertTrue(mUNM.mobileNetworkRequested());
- assertEquals(1, mCM.requested.size());
- assertEquals(1, mCM.legacyTypeMap.size());
- assertEquals(Integer.valueOf(TYPE_MOBILE_HIPRI),
- mCM.legacyTypeMap.values().iterator().next());
+ assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI);
assertFalse(mCM.isDunRequested());
mUNM.stop();
assertFalse(mUNM.mobileNetworkRequested());
- assertTrue(mCM.isEmpty());
+ assertTrue(mCM.hasNoCallbacks());
}
@Test
- public void testCanRequestDunNetwork() throws Exception {
+ public void testRequestsDunNetwork() throws Exception {
assertFalse(mUNM.mobileNetworkRequested());
assertEquals(0, mCM.requested.size());
@@ -141,15 +140,44 @@
mUNM.registerMobileNetworkRequest();
assertTrue(mUNM.mobileNetworkRequested());
- assertEquals(1, mCM.requested.size());
- assertEquals(1, mCM.legacyTypeMap.size());
- assertEquals(Integer.valueOf(TYPE_MOBILE_DUN),
- mCM.legacyTypeMap.values().iterator().next());
+ assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
assertTrue(mCM.isDunRequested());
mUNM.stop();
assertFalse(mUNM.mobileNetworkRequested());
- assertTrue(mCM.isEmpty());
+ assertTrue(mCM.hasNoCallbacks());
+ }
+
+ @Test
+ public void testUpdateMobileRequiredDun() throws Exception {
+ mUNM.start();
+
+ // Test going from no-DUN to DUN correctly re-registers callbacks.
+ mUNM.updateMobileRequiresDun(false);
+ mUNM.registerMobileNetworkRequest();
+ assertTrue(mUNM.mobileNetworkRequested());
+ assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI);
+ assertFalse(mCM.isDunRequested());
+ mUNM.updateMobileRequiresDun(true);
+ assertTrue(mUNM.mobileNetworkRequested());
+ assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
+ assertTrue(mCM.isDunRequested());
+
+ // Test going from DUN to no-DUN correctly re-registers callbacks.
+ mUNM.updateMobileRequiresDun(false);
+ assertTrue(mUNM.mobileNetworkRequested());
+ assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI);
+ assertFalse(mCM.isDunRequested());
+
+ mUNM.stop();
+ assertFalse(mUNM.mobileNetworkRequested());
+ }
+
+ private void assertUpstreamTypeRequested(int upstreamType) throws Exception {
+ assertEquals(1, mCM.requested.size());
+ assertEquals(1, mCM.legacyTypeMap.size());
+ assertEquals(Integer.valueOf(upstreamType),
+ mCM.legacyTypeMap.values().iterator().next());
}
private static class TestConnectivityManager extends ConnectivityManager {
@@ -162,7 +190,7 @@
super(ctx, svc);
}
- boolean isEmpty() {
+ boolean hasNoCallbacks() {
return trackingDefault.isEmpty() &&
listening.isEmpty() &&
requested.isEmpty() &&
@@ -225,6 +253,8 @@
} else if (requested.containsKey(cb)) {
requested.remove(cb);
legacyTypeMap.remove(cb);
+ } else {
+ fail("Unexpected callback removed");
}
assertFalse(trackingDefault.contains(cb));